Browse Source

Merge pull request #623 from neph1/fix_AppStateExplorer

fix AppStateExplorer not finding AppStates extending BaseAppState
Rickard Edén 8 months ago
parent
commit
f87c55b90b
1 changed files with 62 additions and 34 deletions
  1. 62 34
      jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.java

+ 62 - 34
jme3-core/src/com/jme3/gde/core/appstates/NewAppStateVisualPanel1.java

@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  Copyright (c) 2009-2024 jMonkeyEngine
  *  All rights reserved.
  * 
  *  Redistribution and use in source and binary forms, with or without
@@ -31,13 +31,15 @@
  */
 package com.jme3.gde.core.appstates;
 
+import java.io.IOException;
 import java.util.EnumSet;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
 import javax.swing.JPanel;
 import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.api.java.project.JavaProjectConstants;
@@ -48,9 +50,8 @@ import org.netbeans.api.java.source.ClasspathInfo;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.ElementHandle;
 import org.netbeans.api.java.source.JavaSource;
-import org.netbeans.api.java.source.JavaSource.Phase;
-import org.netbeans.api.java.source.Task;
 import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
 import org.netbeans.api.project.SourceGroup;
 import org.netbeans.api.project.Sources;
 import org.openide.util.Exceptions;
@@ -82,57 +83,84 @@ public final class NewAppStateVisualPanel1 extends JPanel {
     }
 
     private List<String> getSources() {
-        Sources sources = proj.getLookup().lookup(Sources.class);
-        final List<String> list = new LinkedList<String>();
+        Sources sources = ProjectUtils.getSources(proj);
+        final List<String> list = new LinkedList<>();
         if (sources != null) {
             SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
             if (groups != null) {
                 for (SourceGroup sourceGroup : groups) {
-                    ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT),
+                    ClasspathInfo cpInfo = ClasspathInfo.create(
+                            ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT),
                             ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.COMPILE),
-                            ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE));
+                            ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE)
+                    );
 
                     Set<SearchScope> set = EnumSet.of(ClassIndex.SearchScope.SOURCE);
                     Set<ElementHandle<TypeElement>> types = cpInfo.getClassIndex().getDeclaredTypes("", NameKind.PREFIX, set);
-                    for (Iterator<ElementHandle<TypeElement>> it = types.iterator(); it.hasNext();) {
-                        final ElementHandle<TypeElement> elementHandle = it.next();
+                    for (ElementHandle<TypeElement> elementHandle : types) {
                         JavaSource js = JavaSource.create(cpInfo);
                         try {
-                            js.runUserActionTask(new Task<CompilationController>() {
-                                public void run(CompilationController control)
-                                        throws Exception {
-                                    control.toPhase(Phase.RESOLVED);
-                                    //TODO: check with proper casting check.. gotta get TypeMirror of Control interface..
-//                                    TypeUtilities util = control.getTypeUtilities();//.isCastable(Types., null)
-//                                    util.isCastable(null, null);
-                                    TypeElement elem = elementHandle.resolve(control);
-                                    if (elem != null) {
-                                        List<? extends TypeMirror> interfaces = elem.getInterfaces();
-                                        for (TypeMirror typeMirror : interfaces) {
-                                            String interfaceName = typeMirror.toString();
-                                            if ("com.jme3.app.state.AppState".equals(interfaceName)) {
-                                                list.add(elem.getQualifiedName().toString());
-                                            }
-                                        }
-                                        TypeMirror superClass = elem.getSuperclass();
-                                        String superClassName = superClass.toString();
-                                        if ("com.jme3.app.state.AbstractAppState".equals(superClassName)) {
-                                            list.add(elem.getQualifiedName().toString());
-                                        }
-                                    }
+                            js.runUserActionTask((CompilationController control) -> {
+                                control.toPhase(JavaSource.Phase.RESOLVED);
+                                TypeElement elem = elementHandle.resolve(control);
+                                if (elem != null && doesInheritFromAppState(elem, control.getTypes())) {
+                                    list.add(elem.getQualifiedName().toString());
                                 }
                             }, false);
-                        } catch (Exception ioe) {
+                        } catch (IOException ioe) {
                             Exceptions.printStackTrace(ioe);
                         }
                     }
-
                 }
             }
         }
         return list;
     }
 
+    /**
+     * Checks recursively if a type inherits from or implements any
+     * AppState-related class/interface.
+     */
+    private boolean doesInheritFromAppState(TypeElement type, Types typeUtils) {
+        if (type == null) {
+            return false;
+        }
+
+        // Check interfaces
+        for (TypeMirror iface : type.getInterfaces()) {
+            if (isAppStateType(iface)) {
+                return true;
+            }
+            if (doesInheritFromAppState((TypeElement) typeUtils.asElement(iface), typeUtils)) {
+                return true;
+            }
+        }
+
+        // Check superclass
+        TypeMirror superClass = type.getSuperclass();
+        if (superClass != null && superClass.getKind() != TypeKind.NONE) {
+            if (isAppStateType(superClass)) {
+                return true;
+            }
+            return doesInheritFromAppState((TypeElement) typeUtils.asElement(superClass), typeUtils);
+        }
+
+        return false;
+    }
+
+    /**
+     * Determines if a TypeMirror corresponds to an AppState-related type.
+     */
+    private boolean isAppStateType(TypeMirror typeMirror) {
+        if (typeMirror == null) {
+            return false;
+        }
+        String className = typeMirror.toString();
+        return "com.jme3.app.state.AppState".equals(className)
+                || "com.jme3.app.state.AbstractAppState".equals(className)
+                || "com.jme3.app.state.BaseAppState".equals(className);
+    }
+
     public void load(Project proj) {
         this.proj = proj;
         scanControls();