mirror of
https://github.com/cincheo/jsweet.git
synced 2025-12-15 15:29:22 +00:00
properly get overload with conflicts
This commit is contained in:
parent
54df1dbe45
commit
4c17cb7502
@ -25,6 +25,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@ -46,6 +47,7 @@ import javax.tools.JavaFileManager;
|
|||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
import org.jsweet.JSweetConfig;
|
import org.jsweet.JSweetConfig;
|
||||||
import org.jsweet.transpiler.JSweetContext;
|
import org.jsweet.transpiler.JSweetContext;
|
||||||
|
|
||||||
@ -90,6 +92,8 @@ import com.sun.tools.javac.util.Name;
|
|||||||
*/
|
*/
|
||||||
public class Util {
|
public class Util {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(Util.class);
|
||||||
|
|
||||||
private Util() {
|
private Util() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,8 +227,8 @@ public class Util {
|
|||||||
* Recursively adds files to the given list.
|
* Recursively adds files to the given list.
|
||||||
*
|
*
|
||||||
* @param filter
|
* @param filter
|
||||||
* the filter predicate to apply (only files matching the
|
* the filter predicate to apply (only files matching the predicate
|
||||||
* predicate will be added)
|
* will be added)
|
||||||
* @param file
|
* @param file
|
||||||
* the root file/directory to look into recursively
|
* the root file/directory to look into recursively
|
||||||
* @param files
|
* @param files
|
||||||
@ -331,8 +335,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the given map with all the variables beeing accessed within the
|
* Fills the given map with all the variables beeing accessed within the given
|
||||||
* given code tree.
|
* code tree.
|
||||||
*/
|
*/
|
||||||
public static void fillAllVariableAccesses(final Map<String, VarSymbol> vars, final JCTree tree) {
|
public static void fillAllVariableAccesses(final Map<String, VarSymbol> vars, final JCTree tree) {
|
||||||
new TreeScanner() {
|
new TreeScanner() {
|
||||||
@ -353,8 +357,7 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the method declaration within the given type, for the given
|
* Finds the method declaration within the given type, for the given invocation.
|
||||||
* invocation.
|
|
||||||
*/
|
*/
|
||||||
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol,
|
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol,
|
||||||
JCMethodInvocation invocation) {
|
JCMethodInvocation invocation) {
|
||||||
@ -364,8 +367,7 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the method in the given type that matches the given name and
|
* Finds the method in the given type that matches the given name and signature.
|
||||||
* signature.
|
|
||||||
*/
|
*/
|
||||||
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol, String methodName,
|
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol, String methodName,
|
||||||
MethodType methodType) {
|
MethodType methodType) {
|
||||||
@ -373,48 +375,84 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the method in the given type that matches the given name and
|
* Finds the method in the given type that matches the given name and signature.
|
||||||
* signature.
|
|
||||||
*/
|
*/
|
||||||
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol, String methodName,
|
public static MethodSymbol findMethodDeclarationInType(Types types, TypeSymbol typeSymbol, String methodName,
|
||||||
MethodType methodType, boolean overrides) {
|
MethodType methodType, boolean overrides) {
|
||||||
|
|
||||||
|
// gathers all the potential method matches
|
||||||
|
List<MethodSymbol> candidates = new LinkedList<>();
|
||||||
|
collectMatchingMethodDeclarationsInType(types, typeSymbol, methodName, methodType, overrides, candidates);
|
||||||
|
|
||||||
|
// score them
|
||||||
|
MethodSymbol bestMatch = null;
|
||||||
|
int lastScore = Integer.MIN_VALUE;
|
||||||
|
for (MethodSymbol candidate : candidates) {
|
||||||
|
int currentScore = getCandidateMethodMatchScore(candidate, methodType, types);
|
||||||
|
if (bestMatch == null || currentScore > lastScore) {
|
||||||
|
bestMatch = candidate;
|
||||||
|
lastScore = currentScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the best match
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("method declaration match for " + typeSymbol + "." + methodName + " - " + methodType + " : "
|
||||||
|
+ bestMatch + " score=" + lastScore);
|
||||||
|
}
|
||||||
|
return bestMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getCandidateMethodMatchScore(MethodSymbol candidate, MethodType methodType, Types types) {
|
||||||
|
|
||||||
|
if (methodType == null || candidate.getParameters().size() != methodType.argtypes.size()) {
|
||||||
|
return -50;
|
||||||
|
}
|
||||||
|
|
||||||
|
int score = 0;
|
||||||
|
for (int i = 0; i < candidate.getParameters().size(); i++) {
|
||||||
|
Type candidateParamType = candidate.getParameters().get(i).type;
|
||||||
|
Type paramType = methodType.argtypes.get(i);
|
||||||
|
|
||||||
|
if (!candidateParamType.equals(paramType)) {
|
||||||
|
score--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void collectMatchingMethodDeclarationsInType(Types types, TypeSymbol typeSymbol, String methodName,
|
||||||
|
MethodType methodType, boolean overrides, List<MethodSymbol> collector) {
|
||||||
if (typeSymbol == null) {
|
if (typeSymbol == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
if (typeSymbol.getEnclosedElements() != null) {
|
if (typeSymbol.getEnclosedElements() != null) {
|
||||||
for (Element element : typeSymbol.getEnclosedElements()) {
|
for (Element element : typeSymbol.getEnclosedElements()) {
|
||||||
if ((element instanceof MethodSymbol) && (methodName.equals(element.getSimpleName().toString())
|
if ((element instanceof MethodSymbol) && (methodName.equals(element.getSimpleName().toString())
|
||||||
|| ((MethodSymbol) element).getKind() == ElementKind.CONSTRUCTOR && ("this".equals(
|
|| ((MethodSymbol) element).getKind() == ElementKind.CONSTRUCTOR
|
||||||
methodName) /* || "super".equals(methodName) */))) {
|
&& ("this".equals(methodName) /* || "super".equals(methodName) */))) {
|
||||||
MethodSymbol methodSymbol = (MethodSymbol) element;
|
MethodSymbol methodSymbol = (MethodSymbol) element;
|
||||||
if (methodType == null) {
|
if (methodType == null) {
|
||||||
return methodSymbol;
|
collector.add(methodSymbol);
|
||||||
}
|
} else if (overrides ? isInvocable(types, methodSymbol.type.asMethodType(), methodType)
|
||||||
if (overrides ? isInvocable(types, methodSymbol.type.asMethodType(), methodType)
|
|
||||||
: isInvocable(types, methodType, methodSymbol.type.asMethodType())) {
|
: isInvocable(types, methodType, methodSymbol.type.asMethodType())) {
|
||||||
return methodSymbol;
|
collector.add(methodSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MethodSymbol result = null;
|
|
||||||
if (typeSymbol instanceof ClassSymbol && ((ClassSymbol) typeSymbol).getSuperclass() != null) {
|
if (typeSymbol instanceof ClassSymbol && ((ClassSymbol) typeSymbol).getSuperclass() != null) {
|
||||||
if (!overrides || !Object.class.getName().equals(((ClassSymbol) typeSymbol).getSuperclass().toString())) {
|
if (!overrides || !Object.class.getName().equals(((ClassSymbol) typeSymbol).getSuperclass().toString())) {
|
||||||
result = findMethodDeclarationInType(types, ((ClassSymbol) typeSymbol).getSuperclass().tsym, methodName,
|
collectMatchingMethodDeclarationsInType(types, ((ClassSymbol) typeSymbol).getSuperclass().tsym,
|
||||||
methodType);
|
methodName, methodType, overrides, collector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
if (typeSymbol instanceof ClassSymbol && ((ClassSymbol) typeSymbol).getInterfaces() != null) {
|
||||||
if (typeSymbol instanceof ClassSymbol && ((ClassSymbol) typeSymbol).getInterfaces() != null) {
|
for (Type t : ((ClassSymbol) typeSymbol).getInterfaces()) {
|
||||||
for (Type t : ((ClassSymbol) typeSymbol).getInterfaces()) {
|
collectMatchingMethodDeclarationsInType(types, t.tsym, methodName, methodType, overrides, collector);
|
||||||
result = findMethodDeclarationInType(types, t.tsym, methodName, methodType);
|
|
||||||
if (result != null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,7 +463,7 @@ public class Util {
|
|||||||
if (typeSymbol == null) {
|
if (typeSymbol == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ignoredTypeNames.contains(typeSymbol.getQualifiedName())) {
|
if (ignoredTypeNames.contains(typeSymbol.getQualifiedName().toString())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeSymbol.getEnclosedElements() != null) {
|
if (typeSymbol.getEnclosedElements() != null) {
|
||||||
@ -527,7 +565,7 @@ public class Util {
|
|||||||
if (typeSymbol == null) {
|
if (typeSymbol == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ignoredTypeNames.contains(typeSymbol.getQualifiedName())) {
|
if (ignoredTypeNames.contains(typeSymbol.getQualifiedName().toString())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (typeSymbol.getEnclosedElements() != null) {
|
if (typeSymbol.getEnclosedElements() != null) {
|
||||||
@ -571,8 +609,7 @@ public class Util {
|
|||||||
* @param types
|
* @param types
|
||||||
* a reference to the types in the compilation scope
|
* a reference to the types in the compilation scope
|
||||||
* @param from
|
* @param from
|
||||||
* the caller method signature to test (contains the parameter
|
* the caller method signature to test (contains the parameter types)
|
||||||
* types)
|
|
||||||
* @param target
|
* @param target
|
||||||
* the callee method signature
|
* the callee method signature
|
||||||
* @return true if the callee can be invoked by the caller
|
* @return true if the callee can be invoked by the caller
|
||||||
@ -610,8 +647,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the given set with all the default methods found in the current
|
* Fills the given set with all the default methods found in the current type
|
||||||
* type and super interfaces.
|
* and super interfaces.
|
||||||
*/
|
*/
|
||||||
public static void findDefaultMethodsInType(Set<Entry<JCClassDecl, JCMethodDecl>> defaultMethods,
|
public static void findDefaultMethodsInType(Set<Entry<JCClassDecl, JCMethodDecl>> defaultMethods,
|
||||||
JSweetContext context, ClassSymbol classSymbol) {
|
JSweetContext context, ClassSymbol classSymbol) {
|
||||||
@ -700,11 +737,10 @@ public class Util {
|
|||||||
private final static Pattern REGEX_CHARS = Pattern.compile("([\\\\*+\\[\\](){}\\$.?\\^|])");
|
private final static Pattern REGEX_CHARS = Pattern.compile("([\\\\*+\\[\\](){}\\$.?\\^|])");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function will escape special characters within a string to ensure
|
* This function will escape special characters within a string to ensure that
|
||||||
* that the string will not be parsed as a regular expression. This is
|
* the string will not be parsed as a regular expression. This is helpful with
|
||||||
* helpful with accepting using input that needs to be used in functions
|
* accepting using input that needs to be used in functions that take a regular
|
||||||
* that take a regular expression as an argument (such as
|
* expression as an argument (such as String.replaceAll(), or String.split()).
|
||||||
* String.replaceAll(), or String.split()).
|
|
||||||
*
|
*
|
||||||
* @param regex
|
* @param regex
|
||||||
* - argument which we wish to escape.
|
* - argument which we wish to escape.
|
||||||
@ -860,8 +896,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the given directory or any of its sub-directory contains one of
|
* Tells if the given directory or any of its sub-directory contains one of the
|
||||||
* the given files.
|
* given files.
|
||||||
*
|
*
|
||||||
* @param dir
|
* @param dir
|
||||||
* the directory to look into
|
* the directory to look into
|
||||||
@ -1022,8 +1058,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively looks up one of the given types in the type hierachy of the
|
* Recursively looks up one of the given types in the type hierachy of the given
|
||||||
* given class.
|
* class.
|
||||||
*
|
*
|
||||||
* @return true if one of the given names is found as a superclass or a
|
* @return true if one of the given names is found as a superclass or a
|
||||||
* superinterface
|
* superinterface
|
||||||
@ -1178,8 +1214,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if that variable is a non-static final field initialized with a
|
* Tells if that variable is a non-static final field initialized with a literal
|
||||||
* literal value.
|
* value.
|
||||||
*/
|
*/
|
||||||
public static boolean isConstantOrNullField(JCVariableDecl var) {
|
public static boolean isConstantOrNullField(JCVariableDecl var) {
|
||||||
return !var.getModifiers().getFlags().contains(Modifier.STATIC) && (var.init == null
|
return !var.getModifiers().getFlags().contains(Modifier.STATIC) && (var.init == null
|
||||||
@ -1243,10 +1279,10 @@ public class Util {
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This method aims at overcoming TypeScrit limitation that forces a parent
|
* This method aims at overcoming TypeScrit limitation that forces a parent
|
||||||
* class to be declared before its child class (it is not the case in Java).
|
* class to be declared before its child class (it is not the case in Java). So
|
||||||
* So far this is a partial implementation that should cover most cases...
|
* far this is a partial implementation that should cover most cases... for a
|
||||||
* for a 100% coverage we would need a much more complicated implementation
|
* 100% coverage we would need a much more complicated implementation that is
|
||||||
* that is probably not worth it.
|
* probably not worth it.
|
||||||
*/
|
*/
|
||||||
public static List<JCClassDecl> getSortedClassDeclarations(List<JCTree> decls) {
|
public static List<JCClassDecl> getSortedClassDeclarations(List<JCTree> decls) {
|
||||||
// return (List<JCClassDecl>)(Object)decls;
|
// return (List<JCClassDecl>)(Object)decls;
|
||||||
@ -1280,8 +1316,8 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the first inner class declaration of the given name in the given
|
* Finds the first inner class declaration of the given name in the given class
|
||||||
* class hierarchy.
|
* hierarchy.
|
||||||
*/
|
*/
|
||||||
public static ClassSymbol findInnerClassDeclaration(ClassSymbol clazz, String name) {
|
public static ClassSymbol findInnerClassDeclaration(ClassSymbol clazz, String name) {
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user