mirror of
https://github.com/processing/processing4.git
synced 2026-02-12 18:10:43 +01:00
trying to tidy things up a bit in CompletionGenerator
This commit is contained in:
@@ -24,10 +24,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -124,79 +121,82 @@ public class CompletionGenerator {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the parent of the expression in a().b, this would give me the return
|
||||
* type of a(), so that we can find all children of a() beginning with b
|
||||
*/
|
||||
public static ASTNode resolveExpression(ASTNode nearestNode,
|
||||
ASTNode expression, boolean noCompare) {
|
||||
log("Resolving " + getNodeAsString(expression) + " noComp "
|
||||
+ noCompare);
|
||||
if (expression instanceof SimpleName) {
|
||||
return findDeclaration2(((SimpleName) expression), nearestNode);
|
||||
} else if (expression instanceof MethodInvocation) {
|
||||
log("3. Method Invo "
|
||||
+ ((MethodInvocation) expression).getName());
|
||||
return findDeclaration2(((MethodInvocation) expression).getName(),
|
||||
nearestNode);
|
||||
} else if (expression instanceof FieldAccess) {
|
||||
log("2. Field access "
|
||||
+ getNodeAsString(((FieldAccess) expression).getExpression()) + "|||"
|
||||
+ getNodeAsString(((FieldAccess) expression).getName()));
|
||||
if (noCompare) {
|
||||
/*
|
||||
* ASTNode ret = findDeclaration2(((FieldAccess) expression).getName(),
|
||||
* nearestNode); log("Found as ->"+getNodeAsString(ret));
|
||||
* return ret;
|
||||
*/
|
||||
return findDeclaration2(((FieldAccess) expression).getName(),
|
||||
nearestNode);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Note how for the next recursion, noCompare is reversed. Let's say
|
||||
* I've typed getABC().quark.nin where nin is incomplete(ninja being the
|
||||
* field), when execution first enters here, it calls resolveExpr again
|
||||
* for "getABC().quark" where we know that quark field must be complete,
|
||||
* so we toggle noCompare. And kaboom.
|
||||
*/
|
||||
return resolveExpression(nearestNode,
|
||||
((FieldAccess) expression).getExpression(),
|
||||
true);
|
||||
}
|
||||
//return findDeclaration2(((FieldAccess) expression).getExpression(), nearestNode);
|
||||
} else if (expression instanceof QualifiedName) {
|
||||
log("1. Resolving "
|
||||
+ ((QualifiedName) expression).getQualifier() + " ||| "
|
||||
+ ((QualifiedName) expression).getName());
|
||||
if (noCompare) { // no compare, as in "abc.hello." need to resolve hello here
|
||||
return findDeclaration2(((QualifiedName) expression).getName(),
|
||||
nearestNode);
|
||||
} else {
|
||||
//User typed "abc.hello.by" (bye being complete), so need to resolve "abc.hello." only
|
||||
return findDeclaration2(((QualifiedName) expression).getQualifier(),
|
||||
nearestNode);
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Find the parent of the expression in a().b, this would give me the return
|
||||
// * type of a(), so that we can find all children of a() beginning with b
|
||||
// */
|
||||
// public static ASTNode resolveExpression(ASTNode nearestNode,
|
||||
// ASTNode expression, boolean noCompare) {
|
||||
// log("Resolving " + getNodeAsString(expression) + " noComp "
|
||||
// + noCompare);
|
||||
// if (expression instanceof SimpleName) {
|
||||
// return findDeclaration2(((SimpleName) expression), nearestNode);
|
||||
// } else if (expression instanceof MethodInvocation) {
|
||||
// log("3. Method Invo "
|
||||
// + ((MethodInvocation) expression).getName());
|
||||
// return findDeclaration2(((MethodInvocation) expression).getName(),
|
||||
// nearestNode);
|
||||
// } else if (expression instanceof FieldAccess) {
|
||||
// log("2. Field access "
|
||||
// + getNodeAsString(((FieldAccess) expression).getExpression()) + "|||"
|
||||
// + getNodeAsString(((FieldAccess) expression).getName()));
|
||||
// if (noCompare) {
|
||||
// /*
|
||||
// * ASTNode ret = findDeclaration2(((FieldAccess) expression).getName(),
|
||||
// * nearestNode); log("Found as ->"+getNodeAsString(ret));
|
||||
// * return ret;
|
||||
// */
|
||||
// return findDeclaration2(((FieldAccess) expression).getName(),
|
||||
// nearestNode);
|
||||
// } else {
|
||||
//
|
||||
// /*
|
||||
// * Note how for the next recursion, noCompare is reversed. Let's say
|
||||
// * I've typed getABC().quark.nin where nin is incomplete(ninja being the
|
||||
// * field), when execution first enters here, it calls resolveExpr again
|
||||
// * for "getABC().quark" where we know that quark field must be complete,
|
||||
// * so we toggle noCompare. And kaboom.
|
||||
// */
|
||||
// return resolveExpression(nearestNode,
|
||||
// ((FieldAccess) expression).getExpression(),
|
||||
// true);
|
||||
// }
|
||||
// //return findDeclaration2(((FieldAccess) expression).getExpression(), nearestNode);
|
||||
// } else if (expression instanceof QualifiedName) {
|
||||
// log("1. Resolving "
|
||||
// + ((QualifiedName) expression).getQualifier() + " ||| "
|
||||
// + ((QualifiedName) expression).getName());
|
||||
// if (noCompare) { // no compare, as in "abc.hello." need to resolve hello here
|
||||
// return findDeclaration2(((QualifiedName) expression).getName(),
|
||||
// nearestNode);
|
||||
// } else {
|
||||
// //User typed "abc.hello.by" (bye being complete), so need to resolve "abc.hello." only
|
||||
// return findDeclaration2(((QualifiedName) expression).getQualifier(),
|
||||
// nearestNode);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the type of the expression in foo.bar().a().b, this would give me the
|
||||
* type of b if it exists in return type of a(). If noCompare is true,
|
||||
* it'll return type of a()
|
||||
*/
|
||||
public static ClassMember resolveExpression3rdParty(PreprocSketch ps, ASTNode nearestNode,
|
||||
static public ClassMember resolveExpression3rdParty(PreprocSketch ps, ASTNode nearestNode,
|
||||
ASTNode astNode, boolean noCompare) {
|
||||
log("Resolve 3rdParty expr-- " + getNodeAsString(astNode)
|
||||
+ " nearest node " + getNodeAsString(nearestNode));
|
||||
if(astNode == null) return null;
|
||||
if (astNode == null) return null;
|
||||
|
||||
ClassMember scopeParent;
|
||||
SimpleType stp;
|
||||
if(astNode instanceof SimpleName){
|
||||
if (astNode instanceof SimpleName){
|
||||
ASTNode decl = findDeclaration2(((SimpleName)astNode),nearestNode);
|
||||
if(decl != null){
|
||||
if (decl != null) {
|
||||
// see if locally defined
|
||||
log(getNodeAsString(astNode)+" found decl -> " + getNodeAsString(decl));
|
||||
|
||||
@@ -225,14 +225,12 @@ public class CompletionGenerator {
|
||||
|
||||
// Convert element class to array class
|
||||
Class<?> arrayClass = getArrayClass(name, ps.classLoader);
|
||||
|
||||
return arrayClass == null ? null : new ClassMember(arrayClass);
|
||||
}
|
||||
}
|
||||
|
||||
return new ClassMember(ps, extracTypeInfo(decl));
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
// or in a predefined class?
|
||||
Class<?> tehClass = findClassIfExists(ps, astNode.toString());
|
||||
if (tehClass != null) {
|
||||
@@ -241,14 +239,13 @@ public class CompletionGenerator {
|
||||
}
|
||||
astNode = astNode.getParent();
|
||||
}
|
||||
|
||||
switch (astNode.getNodeType()) {
|
||||
//TODO: Notice the redundancy in the 3 cases, you can simplify things even more.
|
||||
case ASTNode.FIELD_ACCESS:
|
||||
FieldAccess fa = (FieldAccess) astNode;
|
||||
if (fa.getExpression() == null) {
|
||||
|
||||
// TODO: Check for existence of 'new' keyword. Could be a ClassInstanceCreation
|
||||
|
||||
// Local code or belongs to super class
|
||||
log("FA,Not implemented.");
|
||||
return null;
|
||||
@@ -371,6 +368,7 @@ public class CompletionGenerator {
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case ASTNode.QUALIFIED_NAME:
|
||||
QualifiedName qn = (QualifiedName) astNode;
|
||||
ASTNode temp2 = findDeclaration2(qn.getName(), nearestNode);
|
||||
@@ -436,7 +434,7 @@ public class CompletionGenerator {
|
||||
}
|
||||
|
||||
|
||||
public static Class<?> getArrayClass(String elementClass, ClassLoader classLoader) {
|
||||
static private Class<?> getArrayClass(String elementClass, ClassLoader classLoader) {
|
||||
String name;
|
||||
if (elementClass.startsWith("[")) {
|
||||
// just add a leading "["
|
||||
@@ -468,7 +466,7 @@ public class CompletionGenerator {
|
||||
/**
|
||||
* For a().abc.a123 this would return a123
|
||||
*/
|
||||
static public ASTNode getChildExpression(ASTNode expression) {
|
||||
static private ASTNode getChildExpression(ASTNode expression) {
|
||||
if (expression instanceof SimpleName) {
|
||||
return expression;
|
||||
} else if (expression instanceof FieldAccess) {
|
||||
@@ -485,7 +483,8 @@ public class CompletionGenerator {
|
||||
return null;
|
||||
}
|
||||
|
||||
static public ASTNode getParentExpression(ASTNode expression) {
|
||||
|
||||
static private ASTNode getParentExpression(ASTNode expression) {
|
||||
if (expression instanceof SimpleName) {
|
||||
return expression;
|
||||
} else if (expression instanceof FieldAccess) {
|
||||
@@ -506,7 +505,7 @@ public class CompletionGenerator {
|
||||
/**
|
||||
* Loads classes from .jar files in sketch classpath
|
||||
*/
|
||||
public static List<CompletionCandidate> getMembersForType(PreprocSketch ps,
|
||||
static public List<CompletionCandidate> getMembersForType(PreprocSketch ps,
|
||||
String typeName,
|
||||
String child,
|
||||
boolean noCompare,
|
||||
@@ -516,15 +515,15 @@ public class CompletionGenerator {
|
||||
+ " in class " + typeName + " noCompare " + noCompare + " staticOnly "
|
||||
+ staticOnly);
|
||||
Class<?> probableClass = findClassIfExists(ps, typeName);
|
||||
if(probableClass == null){
|
||||
if (probableClass == null) {
|
||||
log("In GMFT(), class not found.");
|
||||
return candidates;
|
||||
}
|
||||
return getMembersForType(ps, new ClassMember(probableClass), child, noCompare, staticOnly);
|
||||
|
||||
return getMembersForType(ps, new ClassMember(probableClass), child, noCompare, staticOnly);
|
||||
}
|
||||
|
||||
public static ArrayList<CompletionCandidate> getMembersForType(PreprocSketch ps,
|
||||
|
||||
static public ArrayList<CompletionCandidate> getMembersForType(PreprocSketch ps,
|
||||
ClassMember tehClass,
|
||||
String childToLookFor,
|
||||
boolean noCompare,
|
||||
@@ -570,20 +569,16 @@ public class CompletionGenerator {
|
||||
}
|
||||
|
||||
ArrayList<CompletionCandidate> superClassCandidates;
|
||||
if(td.getSuperclassType() != null){
|
||||
if (td.getSuperclassType() != null) {
|
||||
log(getNodeAsString(td.getSuperclassType()) + " <-Looking into superclass of " + tehClass);
|
||||
superClassCandidates = getMembersForType(ps, new ClassMember(ps, td
|
||||
.getSuperclassType()),
|
||||
childToLookFor, noCompare, staticOnly);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClassMember cm = new ClassMember(ps, td.getSuperclassType());
|
||||
superClassCandidates =
|
||||
getMembersForType(ps, cm, childToLookFor, noCompare, staticOnly);
|
||||
} else {
|
||||
superClassCandidates = getMembersForType(ps, new ClassMember(Object.class),
|
||||
childToLookFor, noCompare, staticOnly);
|
||||
}
|
||||
for (CompletionCandidate cc : superClassCandidates) {
|
||||
candidates.add(cc);
|
||||
}
|
||||
candidates.addAll(superClassCandidates);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@@ -650,7 +645,8 @@ public class CompletionGenerator {
|
||||
return candidates;
|
||||
}
|
||||
|
||||
private static boolean notStatic(List<org.eclipse.jdt.core.dom.Modifier> modifiers) {
|
||||
|
||||
static private boolean notStatic(List<org.eclipse.jdt.core.dom.Modifier> modifiers) {
|
||||
for (org.eclipse.jdt.core.dom.Modifier m : modifiers) {
|
||||
if (m.isStatic()) return false;
|
||||
}
|
||||
@@ -662,7 +658,7 @@ public class CompletionGenerator {
|
||||
* Searches for the particular class in the default list of imports as well as
|
||||
* the Sketch classpath
|
||||
*/
|
||||
protected static Class<?> findClassIfExists(PreprocSketch ps, String className){
|
||||
static private Class<?> findClassIfExists(PreprocSketch ps, String className){
|
||||
if (className == null){
|
||||
return null;
|
||||
}
|
||||
@@ -670,16 +666,16 @@ public class CompletionGenerator {
|
||||
if (className.indexOf('.') >= 0) {
|
||||
// Figure out what is package and what is class
|
||||
String[] parts = className.split("\\.");
|
||||
String newClassName = parts[0];
|
||||
StringBuilder newClassName = new StringBuilder(parts[0]);
|
||||
int i = 1;
|
||||
while (i < parts.length &&
|
||||
ps.classPath.isPackage(newClassName)) {
|
||||
newClassName = newClassName + "/" + parts[i++];
|
||||
ps.classPath.isPackage(newClassName.toString())) {
|
||||
newClassName.append('/').append(parts[i++]);
|
||||
}
|
||||
while (i < parts.length) {
|
||||
newClassName = newClassName + "$" + parts[i++];
|
||||
newClassName.append('$').append(parts[i++]);
|
||||
}
|
||||
className = newClassName.replace('/', '.');
|
||||
className = newClassName.toString().replace('/', '.');
|
||||
}
|
||||
|
||||
// First, see if the classname is a fully qualified name and loads straightaway
|
||||
@@ -724,9 +720,9 @@ public class CompletionGenerator {
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(name -> name != null)
|
||||
.filter(Objects::nonNull)
|
||||
.map(name -> loadClass(name, ps.classLoader))
|
||||
.filter(cls -> cls != null)
|
||||
.filter(Objects::nonNull)
|
||||
.findAny())
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
@@ -734,7 +730,7 @@ public class CompletionGenerator {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
protected static Class<?> loadClass(String className, ClassLoader classLoader){
|
||||
static private Class<?> loadClass(String className, ClassLoader classLoader){
|
||||
Class<?> tehClass = null;
|
||||
if (className != null) {
|
||||
try {
|
||||
@@ -746,7 +742,7 @@ public class CompletionGenerator {
|
||||
return tehClass;
|
||||
}
|
||||
|
||||
public static ClassMember definedIn3rdPartyClass(PreprocSketch ps, String className,String memberName){
|
||||
static ClassMember definedIn3rdPartyClass(PreprocSketch ps, String className,String memberName){
|
||||
Class<?> probableClass = findClassIfExists(ps, className);
|
||||
if (probableClass == null) {
|
||||
log("Couldn't load " + className);
|
||||
@@ -759,7 +755,8 @@ public class CompletionGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public static ClassMember definedIn3rdPartyClass(PreprocSketch ps, ClassMember tehClass,String memberName){
|
||||
|
||||
static ClassMember definedIn3rdPartyClass(PreprocSketch ps, ClassMember tehClass,String memberName){
|
||||
if(tehClass == null)
|
||||
return null;
|
||||
log("definedIn3rdPartyClass-> Looking for " + memberName
|
||||
@@ -813,7 +810,7 @@ public class CompletionGenerator {
|
||||
}
|
||||
|
||||
|
||||
protected static ASTNode findClosestParentNode(int lineNumber, ASTNode node) {
|
||||
static private ASTNode findClosestParentNode(int lineNumber, ASTNode node) {
|
||||
// Base.loge("Props of " + node.getClass().getName());
|
||||
for (StructuralPropertyDescriptor prop : (Iterable<StructuralPropertyDescriptor>) node
|
||||
.structuralPropertiesForType()) {
|
||||
@@ -847,7 +844,8 @@ public class CompletionGenerator {
|
||||
return node;
|
||||
}
|
||||
|
||||
protected static ASTNode findClosestNode(int lineNumber, ASTNode node) {
|
||||
|
||||
static private ASTNode findClosestNode(int lineNumber, ASTNode node) {
|
||||
log("findClosestNode to line " + lineNumber);
|
||||
ASTNode parent = findClosestParentNode(lineNumber, node);
|
||||
log("findClosestParentNode returned " + getNodeAsString(parent));
|
||||
@@ -884,9 +882,9 @@ public class CompletionGenerator {
|
||||
/**
|
||||
* Fetches line number of the node in its CompilationUnit.
|
||||
*/
|
||||
public static int getLineNumber(ASTNode node) {
|
||||
return ((CompilationUnit) node.getRoot()).getLineNumber(node
|
||||
.getStartPosition());
|
||||
static public int getLineNumber(ASTNode node) {
|
||||
CompilationUnit cu = (CompilationUnit) node.getRoot();
|
||||
return cu.getLineNumber(node.getStartPosition());
|
||||
}
|
||||
|
||||
|
||||
@@ -912,8 +910,7 @@ public class CompletionGenerator {
|
||||
* ASTNode for ex, and it tries its level best to locate its declaration in
|
||||
* the AST. It really does.
|
||||
*/
|
||||
protected static ASTNode findDeclaration(Name findMe) {
|
||||
|
||||
static protected ASTNode findDeclaration(Name findMe) {
|
||||
// WARNING: You're entering the Rube Goldberg territory of Experimental Mode.
|
||||
// To debug this code, thou must take the Recursive Leap of Faith.
|
||||
|
||||
@@ -961,7 +958,6 @@ public class CompletionGenerator {
|
||||
return definedIn(declaringClass, ((MethodInvocation) parent)
|
||||
.getName().toString(), constrains);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
parent = parent.getParent(); // Move one up the ast. V V IMP!!
|
||||
@@ -1104,7 +1100,7 @@ public class CompletionGenerator {
|
||||
/**
|
||||
* A variation of findDeclaration() but accepts an alternate parent ASTNode
|
||||
*/
|
||||
protected static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) {
|
||||
static protected ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) {
|
||||
ASTNode declaringClass;
|
||||
ASTNode parent = findMe.getParent();
|
||||
ASTNode ret;
|
||||
@@ -1327,18 +1323,18 @@ public class CompletionGenerator {
|
||||
* @author quarkninja
|
||||
*
|
||||
*/
|
||||
public static class ClassMember {
|
||||
static class ClassMember {
|
||||
private Field field;
|
||||
private Method method;
|
||||
private Constructor<?> cons;
|
||||
private Class<?> thisclass;
|
||||
private String stringVal;
|
||||
private Class<?> thisClass;
|
||||
private final String stringVal;
|
||||
private String classType;
|
||||
private ASTNode astNode;
|
||||
private ASTNode declaringNode;
|
||||
|
||||
public ClassMember(Class<?> m) {
|
||||
thisclass = m;
|
||||
thisClass = m;
|
||||
stringVal = "Predefined Class " + m.getName();
|
||||
classType = m.getName();
|
||||
}
|
||||
@@ -1357,11 +1353,11 @@ public class CompletionGenerator {
|
||||
classType = m.getType().getName();
|
||||
}
|
||||
|
||||
public ClassMember(Constructor<?> m) {
|
||||
cons = m;
|
||||
stringVal = "Cons " + " " + m.getName() + " defined in "
|
||||
+ m.getDeclaringClass().getName();
|
||||
}
|
||||
// public ClassMember(Constructor<?> m) {
|
||||
// cons = m;
|
||||
// stringVal = "Cons " + " " + m.getName() + " defined in "
|
||||
// + m.getDeclaringClass().getName();
|
||||
// }
|
||||
|
||||
public ClassMember(PreprocSketch ps, ASTNode node){
|
||||
astNode = node;
|
||||
@@ -1380,7 +1376,7 @@ public class CompletionGenerator {
|
||||
if(decl == null){
|
||||
// a predefined type
|
||||
classType = stp.getName().toString();
|
||||
thisclass = findClassIfExists(ps, classType);
|
||||
thisClass = findClassIfExists(ps, classType);
|
||||
}
|
||||
else{
|
||||
// a local type
|
||||
@@ -1390,7 +1386,7 @@ public class CompletionGenerator {
|
||||
}
|
||||
|
||||
public Class<?> getClass_() {
|
||||
return thisclass;
|
||||
return thisClass;
|
||||
}
|
||||
|
||||
public ASTNode getDeclaringNode(){
|
||||
@@ -1405,13 +1401,13 @@ public class CompletionGenerator {
|
||||
return method;
|
||||
}
|
||||
|
||||
public Constructor<?> getCons() {
|
||||
return cons;
|
||||
}
|
||||
// public Constructor<?> getCons() {
|
||||
// return cons;
|
||||
// }
|
||||
|
||||
public ASTNode getASTNode(){
|
||||
return astNode;
|
||||
}
|
||||
// public ASTNode getASTNode(){
|
||||
// return astNode;
|
||||
// }
|
||||
|
||||
public String toString() {
|
||||
return stringVal;
|
||||
@@ -1426,7 +1422,7 @@ public class CompletionGenerator {
|
||||
/**
|
||||
* Find the SimpleType from FD, SVD, VDS, etc
|
||||
*/
|
||||
public static SimpleType extracTypeInfo(ASTNode node) {
|
||||
static SimpleType extracTypeInfo(ASTNode node) {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1456,7 +1452,7 @@ public class CompletionGenerator {
|
||||
}
|
||||
|
||||
|
||||
static public Type extracTypeInfo2(ASTNode node) {
|
||||
static Type extracTypeInfo2(ASTNode node) {
|
||||
Messages.log("* extracTypeInfo2");
|
||||
if (node == null)
|
||||
return null;
|
||||
@@ -1868,7 +1864,7 @@ public class CompletionGenerator {
|
||||
if (expr == null) {
|
||||
log("Expr is null");
|
||||
} else {
|
||||
boolean isArray = expr.thisclass != null && expr.thisclass.isArray();
|
||||
boolean isArray = expr.thisClass != null && expr.thisClass.isArray();
|
||||
boolean isSimpleType = (expr.astNode != null) &&
|
||||
expr.astNode.getNodeType() == ASTNode.SIMPLE_TYPE;
|
||||
boolean isMethod = expr.method != null;
|
||||
|
||||
Reference in New Issue
Block a user