|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2009-2010 jMonkeyEngine |
| 2 | + * Copyright (c) 2009-2024 jMonkeyEngine |
3 | 3 | * All rights reserved.
|
4 | 4 | *
|
5 | 5 | * Redistribution and use in source and binary forms, with or without
|
|
31 | 31 | */
|
32 | 32 | package com.jme3.gde.core.appstates;
|
33 | 33 |
|
| 34 | +import java.io.IOException; |
| 35 | +import java.util.ArrayList; |
| 36 | +import java.util.Collections; |
34 | 37 | import java.util.EnumSet;
|
35 |
| -import java.util.Iterator; |
36 |
| -import java.util.LinkedList; |
37 | 38 | import java.util.List;
|
38 | 39 | import java.util.Set;
|
39 | 40 | import javax.lang.model.element.TypeElement;
|
| 41 | +import javax.lang.model.type.TypeKind; |
40 | 42 | import javax.lang.model.type.TypeMirror;
|
| 43 | +import javax.lang.model.util.Types; |
41 | 44 | import javax.swing.JPanel;
|
42 | 45 | import org.netbeans.api.java.classpath.ClassPath;
|
43 | 46 | import org.netbeans.api.java.project.JavaProjectConstants;
|
|
48 | 51 | import org.netbeans.api.java.source.CompilationController;
|
49 | 52 | import org.netbeans.api.java.source.ElementHandle;
|
50 | 53 | import org.netbeans.api.java.source.JavaSource;
|
51 |
| -import org.netbeans.api.java.source.JavaSource.Phase; |
52 |
| -import org.netbeans.api.java.source.Task; |
53 | 54 | import org.netbeans.api.project.Project;
|
| 55 | +import org.netbeans.api.project.ProjectUtils; |
54 | 56 | import org.netbeans.api.project.SourceGroup;
|
55 | 57 | import org.netbeans.api.project.Sources;
|
| 58 | +import org.openide.filesystems.FileObject; |
56 | 59 | import org.openide.util.Exceptions;
|
57 | 60 |
|
58 | 61 | @SuppressWarnings({"unchecked", "rawtypes"})
|
@@ -82,57 +85,103 @@ private void scanControls() {
|
82 | 85 | }
|
83 | 86 |
|
84 | 87 | private List<String> getSources() {
|
85 |
| - Sources sources = proj.getLookup().lookup(Sources.class); |
86 |
| - final List<String> list = new LinkedList<String>(); |
87 |
| - if (sources != null) { |
| 88 | + Project root = ProjectUtils.rootOf(proj); |
| 89 | + Set<Project> containedProjects = ProjectUtils.getContainedProjects(root, true); |
| 90 | + List<Project> projects = new ArrayList<>(); |
| 91 | + projects.add(root); |
| 92 | + if (containedProjects != null) { |
| 93 | + projects.addAll(containedProjects); |
| 94 | + } |
| 95 | + if (projects.isEmpty()) { |
| 96 | + return Collections.emptyList(); |
| 97 | + } |
| 98 | + |
| 99 | + List<String> list = new ArrayList<>(); |
| 100 | + for (Project project : projects) { |
| 101 | + Sources sources = ProjectUtils.getSources(project); |
| 102 | + if (sources == null) { |
| 103 | + continue; |
| 104 | + } |
| 105 | + |
88 | 106 | SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
|
89 |
| - if (groups != null) { |
90 |
| - for (SourceGroup sourceGroup : groups) { |
91 |
| - ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT), |
92 |
| - ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.COMPILE), |
93 |
| - ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE)); |
94 |
| - |
95 |
| - Set<SearchScope> set = EnumSet.of(ClassIndex.SearchScope.SOURCE); |
96 |
| - Set<ElementHandle<TypeElement>> types = cpInfo.getClassIndex().getDeclaredTypes("", NameKind.PREFIX, set); |
97 |
| - for (Iterator<ElementHandle<TypeElement>> it = types.iterator(); it.hasNext();) { |
98 |
| - final ElementHandle<TypeElement> elementHandle = it.next(); |
99 |
| - JavaSource js = JavaSource.create(cpInfo); |
100 |
| - try { |
101 |
| - js.runUserActionTask(new Task<CompilationController>() { |
102 |
| - public void run(CompilationController control) |
103 |
| - throws Exception { |
104 |
| - control.toPhase(Phase.RESOLVED); |
105 |
| - //TODO: check with proper casting check.. gotta get TypeMirror of Control interface.. |
106 |
| -// TypeUtilities util = control.getTypeUtilities();//.isCastable(Types., null) |
107 |
| -// util.isCastable(null, null); |
108 |
| - TypeElement elem = elementHandle.resolve(control); |
109 |
| - if (elem != null) { |
110 |
| - List<? extends TypeMirror> interfaces = elem.getInterfaces(); |
111 |
| - for (TypeMirror typeMirror : interfaces) { |
112 |
| - String interfaceName = typeMirror.toString(); |
113 |
| - if ("com.jme3.app.state.AppState".equals(interfaceName)) { |
114 |
| - list.add(elem.getQualifiedName().toString()); |
115 |
| - } |
116 |
| - } |
117 |
| - TypeMirror superClass = elem.getSuperclass(); |
118 |
| - String superClassName = superClass.toString(); |
119 |
| - if ("com.jme3.app.state.AbstractAppState".equals(superClassName)) { |
120 |
| - list.add(elem.getQualifiedName().toString()); |
121 |
| - } |
122 |
| - } |
123 |
| - } |
124 |
| - }, false); |
125 |
| - } catch (Exception ioe) { |
126 |
| - Exceptions.printStackTrace(ioe); |
127 |
| - } |
128 |
| - } |
| 107 | + if (groups == null) { |
| 108 | + continue; |
| 109 | + } |
129 | 110 |
|
| 111 | + for (SourceGroup sourceGroup : groups) { |
| 112 | + FileObject rootFolder = sourceGroup.getRootFolder(); |
| 113 | + ClasspathInfo cpInfo = ClasspathInfo.create( |
| 114 | + ClassPath.getClassPath(rootFolder, ClassPath.BOOT), |
| 115 | + ClassPath.getClassPath(rootFolder, ClassPath.COMPILE), |
| 116 | + ClassPath.getClassPath(rootFolder, ClassPath.SOURCE) |
| 117 | + ); |
| 118 | + |
| 119 | + Set<SearchScope> set = EnumSet.of(ClassIndex.SearchScope.SOURCE); |
| 120 | + Set<ElementHandle<TypeElement>> types = cpInfo.getClassIndex().getDeclaredTypes("", NameKind.PREFIX, set); |
| 121 | + for (ElementHandle<TypeElement> elementHandle : types) { |
| 122 | + JavaSource js = JavaSource.create(cpInfo); |
| 123 | + try { |
| 124 | + js.runUserActionTask((CompilationController control) -> { |
| 125 | + control.toPhase(JavaSource.Phase.RESOLVED); |
| 126 | + TypeElement elem = elementHandle.resolve(control); |
| 127 | + if (elem != null && doesInheritFromAppState(elem, control.getTypes())) { |
| 128 | + list.add(elem.getQualifiedName().toString()); |
| 129 | + } |
| 130 | + }, false); |
| 131 | + } catch (IOException ioe) { |
| 132 | + Exceptions.printStackTrace(ioe); |
| 133 | + } |
130 | 134 | }
|
131 | 135 | }
|
132 | 136 | }
|
| 137 | + |
133 | 138 | return list;
|
134 | 139 | }
|
135 | 140 |
|
| 141 | + /** |
| 142 | + * Checks recursively if a type inherits from or implements any |
| 143 | + * AppState-related class/interface. |
| 144 | + */ |
| 145 | + private boolean doesInheritFromAppState(TypeElement type, Types typeUtils) { |
| 146 | + if (type == null) { |
| 147 | + return false; |
| 148 | + } |
| 149 | + |
| 150 | + // Check interfaces |
| 151 | + for (TypeMirror iface : type.getInterfaces()) { |
| 152 | + if (isAppStateType(iface)) { |
| 153 | + return true; |
| 154 | + } |
| 155 | + if (doesInheritFromAppState((TypeElement) typeUtils.asElement(iface), typeUtils)) { |
| 156 | + return true; |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + // Check superclass |
| 161 | + TypeMirror superClass = type.getSuperclass(); |
| 162 | + if (superClass != null && superClass.getKind() != TypeKind.NONE) { |
| 163 | + if (isAppStateType(superClass)) { |
| 164 | + return true; |
| 165 | + } |
| 166 | + return doesInheritFromAppState((TypeElement) typeUtils.asElement(superClass), typeUtils); |
| 167 | + } |
| 168 | + |
| 169 | + return false; |
| 170 | + } |
| 171 | + |
| 172 | + /** |
| 173 | + * Determines if a TypeMirror corresponds to an AppState-related type. |
| 174 | + */ |
| 175 | + private boolean isAppStateType(TypeMirror typeMirror) { |
| 176 | + if (typeMirror == null) { |
| 177 | + return false; |
| 178 | + } |
| 179 | + String className = typeMirror.toString(); |
| 180 | + return "com.jme3.app.state.AppState".equals(className) |
| 181 | + || "com.jme3.app.state.AbstractAppState".equals(className) |
| 182 | + || "com.jme3.app.state.BaseAppState".equals(className); |
| 183 | + } |
| 184 | + |
136 | 185 | public void load(Project proj) {
|
137 | 186 | this.proj = proj;
|
138 | 187 | scanControls();
|
|
0 commit comments