|
Lines 31-39
Link Here
|
| 31 |
//extra reference info |
31 |
//extra reference info |
| 32 |
public char[][][] allSuperDeclaringTypeNames; |
32 |
public char[][][] allSuperDeclaringTypeNames; |
| 33 |
|
33 |
|
|
|
34 |
// This is set only if focus is null. In these cases |
| 35 |
// it will be hard to determine if the super class is of the same package |
| 36 |
// at a latter point. Hence, this array is created with all the super class |
| 37 |
// names of the same package name as of the matching class name. |
| 38 |
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=357547 |
| 39 |
private char[][][] samePkgSuperDeclaringTypeNames; |
| 40 |
|
| 34 |
private MatchLocator matchLocator; |
41 |
private MatchLocator matchLocator; |
| 35 |
//method declarations which parameters verification fail |
42 |
//method declarations which parameters verification fail |
| 36 |
private HashMap methodDeclarationsWithInvalidParam = new HashMap(); |
43 |
private HashMap methodDeclarationsWithInvalidParam = new HashMap(); |
|
|
44 |
|
| 37 |
|
45 |
|
| 38 |
public MethodLocator(MethodPattern pattern) { |
46 |
public MethodLocator(MethodPattern pattern) { |
| 39 |
super(pattern); |
47 |
super(pattern); |
|
Lines 75-88
Link Here
|
| 75 |
start = System.currentTimeMillis(); |
83 |
start = System.currentTimeMillis(); |
| 76 |
} |
84 |
} |
| 77 |
try { |
85 |
try { |
| 78 |
this.allSuperDeclaringTypeNames = |
86 |
SuperTypeNamesCollector namesCollector = |
| 79 |
new SuperTypeNamesCollector( |
87 |
new SuperTypeNamesCollector( |
| 80 |
this.pattern, |
88 |
this.pattern, |
| 81 |
this.pattern.declaringSimpleName, |
89 |
this.pattern.declaringSimpleName, |
| 82 |
this.pattern.declaringQualification, |
90 |
this.pattern.declaringQualification, |
| 83 |
locator, |
91 |
locator, |
| 84 |
this.pattern.declaringType, |
92 |
this.pattern.declaringType, |
| 85 |
locator.progressMonitor).collect(); |
93 |
locator.progressMonitor); |
|
|
94 |
this.allSuperDeclaringTypeNames = namesCollector.collect(); |
| 95 |
this.samePkgSuperDeclaringTypeNames = namesCollector.getSamePackageSuperTypeNames(); |
| 86 |
this.matchLocator = locator; |
96 |
this.matchLocator = locator; |
| 87 |
} catch (JavaModelException e) { |
97 |
} catch (JavaModelException e) { |
| 88 |
// inaccurate matches will be found |
98 |
// inaccurate matches will be found |
|
Lines 109-115
Link Here
|
| 109 |
* this message send or not. |
119 |
* this message send or not. |
| 110 |
*/ |
120 |
*/ |
| 111 |
protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) { |
121 |
protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) { |
| 112 |
return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess(); |
122 |
return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess() |
|
|
123 |
&& !(method.isDefault() && this.pattern.focus != null && |
| 124 |
!CharOperation.equals(this.pattern.declaringQualification, method.declaringClass.qualifiedPackageName())); |
| 113 |
} |
125 |
} |
| 114 |
public int match(ASTNode node, MatchingNodeSet nodeSet) { |
126 |
public int match(ASTNode node, MatchingNodeSet nodeSet) { |
| 115 |
int declarationsLevel = IMPOSSIBLE_MATCH; |
127 |
int declarationsLevel = IMPOSSIBLE_MATCH; |
|
Lines 631-637
Link Here
|
| 631 |
subType = CharOperation.compareWith(this.pattern.declaringQualification, method.declaringClass.fPackage.shortReadableName()) == 0; |
643 |
subType = CharOperation.compareWith(this.pattern.declaringQualification, method.declaringClass.fPackage.shortReadableName()) == 0; |
| 632 |
} |
644 |
} |
| 633 |
int declaringLevel = subType |
645 |
int declaringLevel = subType |
| 634 |
? resolveLevelAsSubtype(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass, method.selector, null) |
646 |
? resolveLevelAsSubtype(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass, method.selector, null, method.declaringClass.qualifiedPackageName(), method.isDefault()) |
| 635 |
: resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass); |
647 |
: resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass); |
| 636 |
return (methodLevel & MATCH_LEVEL_MASK) > (declaringLevel & MATCH_LEVEL_MASK) ? declaringLevel : methodLevel; // return the weaker match |
648 |
return (methodLevel & MATCH_LEVEL_MASK) > (declaringLevel & MATCH_LEVEL_MASK) ? declaringLevel : methodLevel; // return the weaker match |
| 637 |
} |
649 |
} |
|
Lines 664-677
Link Here
|
| 664 |
int declaringLevel; |
676 |
int declaringLevel; |
| 665 |
if (isVirtualInvoke(method, messageSend) && (messageSend.actualReceiverType instanceof ReferenceBinding)) { |
677 |
if (isVirtualInvoke(method, messageSend) && (messageSend.actualReceiverType instanceof ReferenceBinding)) { |
| 666 |
ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType; |
678 |
ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType; |
| 667 |
declaringLevel = resolveLevelAsSubtype(this.pattern.declaringSimpleName, this.pattern.declaringQualification, methodReceiverType, method.selector, method.parameters); |
679 |
declaringLevel = resolveLevelAsSubtype(this.pattern.declaringSimpleName, this.pattern.declaringQualification, methodReceiverType, method.selector, method.parameters, methodReceiverType.qualifiedPackageName(), method.isDefault()); |
| 668 |
if (declaringLevel == IMPOSSIBLE_MATCH) { |
680 |
if (declaringLevel == IMPOSSIBLE_MATCH) { |
| 669 |
if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) { |
681 |
if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) { |
| 670 |
declaringLevel = INACCURATE_MATCH; |
682 |
declaringLevel = INACCURATE_MATCH; |
| 671 |
} else { |
683 |
} else { |
| 672 |
if (resolveLevelAsSuperInvocation(methodReceiverType, method.parameters, true)) { |
684 |
char[][][] superTypeNames = (method.isDefault() && this.pattern.focus == null) ? this.samePkgSuperDeclaringTypeNames: this.allSuperDeclaringTypeNames; |
| 673 |
declaringLevel = methodLevel // since this is an ACCURATE_MATCH so return the possibly weaker match |
685 |
if (superTypeNames != null && resolveLevelAsSuperInvocation(methodReceiverType, method.parameters, superTypeNames, true)) { |
| 674 |
| SUPER_INVOCATION_FLAVOR; // this is an overridden method => add flavor to returned level |
686 |
declaringLevel = methodLevel // since this is an ACCURATE_MATCH so return the possibly weaker match |
|
|
687 |
| SUPER_INVOCATION_FLAVOR; // this is an overridden method => add flavor to returned level |
| 675 |
} |
688 |
} |
| 676 |
} |
689 |
} |
| 677 |
} |
690 |
} |
|
Lines 692-702
Link Here
|
| 692 |
* Returns INACCURATE_MATCH if resolve fails |
705 |
* Returns INACCURATE_MATCH if resolve fails |
| 693 |
* Returns IMPOSSIBLE_MATCH if it doesn't. |
706 |
* Returns IMPOSSIBLE_MATCH if it doesn't. |
| 694 |
*/ |
707 |
*/ |
| 695 |
protected int resolveLevelAsSubtype(char[] simplePattern, char[] qualifiedPattern, ReferenceBinding type, char[] methodName, TypeBinding[] argumentTypes) { |
708 |
protected int resolveLevelAsSubtype(char[] simplePattern, char[] qualifiedPattern, ReferenceBinding type, char[] methodName, TypeBinding[] argumentTypes, char[] packageName, boolean isDefault) { |
| 696 |
if (type == null) return INACCURATE_MATCH; |
709 |
if (type == null) return INACCURATE_MATCH; |
| 697 |
|
710 |
|
| 698 |
int level = resolveLevelForType(simplePattern, qualifiedPattern, type); |
711 |
int level = resolveLevelForType(simplePattern, qualifiedPattern, type); |
| 699 |
if (level != IMPOSSIBLE_MATCH) { |
712 |
if (level != IMPOSSIBLE_MATCH) { |
|
|
713 |
if (isDefault && !CharOperation.equals(packageName, type.qualifiedPackageName())) { |
| 714 |
return IMPOSSIBLE_MATCH; |
| 715 |
} |
| 700 |
MethodBinding method = argumentTypes == null ? null : getMethodBinding(type, methodName, argumentTypes); |
716 |
MethodBinding method = argumentTypes == null ? null : getMethodBinding(type, methodName, argumentTypes); |
| 701 |
if (((method != null && !method.isAbstract()) || !type.isAbstract()) && !type.isInterface()) { // if concrete, then method is overridden |
717 |
if (((method != null && !method.isAbstract()) || !type.isAbstract()) && !type.isInterface()) { // if concrete, then method is overridden |
| 702 |
level |= OVERRIDDEN_METHOD_FLAVOR; |
718 |
level |= OVERRIDDEN_METHOD_FLAVOR; |
|
Lines 706-712
Link Here
|
| 706 |
|
722 |
|
| 707 |
// matches superclass |
723 |
// matches superclass |
| 708 |
if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { |
724 |
if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { |
| 709 |
level = resolveLevelAsSubtype(simplePattern, qualifiedPattern, type.superclass(), methodName, argumentTypes); |
725 |
level = resolveLevelAsSubtype(simplePattern, qualifiedPattern, type.superclass(), methodName, argumentTypes, packageName, isDefault); |
| 710 |
if (level != IMPOSSIBLE_MATCH) { |
726 |
if (level != IMPOSSIBLE_MATCH) { |
| 711 |
if (argumentTypes != null) { |
727 |
if (argumentTypes != null) { |
| 712 |
// need to verify if method may be overridden |
728 |
// need to verify if method may be overridden |
|
Lines 730-736
Link Here
|
| 730 |
ReferenceBinding[] interfaces = type.superInterfaces(); |
746 |
ReferenceBinding[] interfaces = type.superInterfaces(); |
| 731 |
if (interfaces == null) return INACCURATE_MATCH; |
747 |
if (interfaces == null) return INACCURATE_MATCH; |
| 732 |
for (int i = 0; i < interfaces.length; i++) { |
748 |
for (int i = 0; i < interfaces.length; i++) { |
| 733 |
level = resolveLevelAsSubtype(simplePattern, qualifiedPattern, interfaces[i], methodName, null); |
749 |
level = resolveLevelAsSubtype(simplePattern, qualifiedPattern, interfaces[i], methodName, null, packageName, isDefault); |
| 734 |
if (level != IMPOSSIBLE_MATCH) { |
750 |
if (level != IMPOSSIBLE_MATCH) { |
| 735 |
if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden |
751 |
if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden |
| 736 |
level |= OVERRIDDEN_METHOD_FLAVOR; |
752 |
level |= OVERRIDDEN_METHOD_FLAVOR; |
|
Lines 745-754
Link Here
|
| 745 |
* Return whether the given type binding or one of its possible super interfaces |
761 |
* Return whether the given type binding or one of its possible super interfaces |
| 746 |
* matches a type in the declaring type names hierarchy. |
762 |
* matches a type in the declaring type names hierarchy. |
| 747 |
*/ |
763 |
*/ |
| 748 |
private boolean resolveLevelAsSuperInvocation(ReferenceBinding type, TypeBinding[] argumentTypes, boolean methodAlreadyVerified) { |
764 |
private boolean resolveLevelAsSuperInvocation(ReferenceBinding type, TypeBinding[] argumentTypes, char[][][] superTypeNames, boolean methodAlreadyVerified) { |
| 749 |
char[][] compoundName = type.compoundName; |
765 |
char[][] compoundName = type.compoundName; |
| 750 |
for (int i = 0, max = this.allSuperDeclaringTypeNames.length; i < max; i++) { |
766 |
for (int i = 0, max = superTypeNames.length; i < max; i++) { |
| 751 |
if (CharOperation.equals(this.allSuperDeclaringTypeNames[i], compoundName)) { |
767 |
if (CharOperation.equals(superTypeNames[i], compoundName)) { |
| 752 |
// need to verify if the type implements the pattern method |
768 |
// need to verify if the type implements the pattern method |
| 753 |
if (methodAlreadyVerified) return true; // already verified before enter into this method (see resolveLevel(MessageSend)) |
769 |
if (methodAlreadyVerified) return true; // already verified before enter into this method (see resolveLevel(MessageSend)) |
| 754 |
MethodBinding[] methods = type.getMethods(this.pattern.selector); |
770 |
MethodBinding[] methods = type.getMethods(this.pattern.selector); |
|
Lines 780-786
Link Here
|
| 780 |
ReferenceBinding[] interfaces = type.superInterfaces(); |
796 |
ReferenceBinding[] interfaces = type.superInterfaces(); |
| 781 |
if (interfaces == null) return false; |
797 |
if (interfaces == null) return false; |
| 782 |
for (int i = 0; i < interfaces.length; i++) { |
798 |
for (int i = 0; i < interfaces.length; i++) { |
| 783 |
if (resolveLevelAsSuperInvocation(interfaces[i], argumentTypes, false)) { |
799 |
if (resolveLevelAsSuperInvocation(interfaces[i], argumentTypes, superTypeNames, false)) { |
| 784 |
return true; |
800 |
return true; |
| 785 |
} |
801 |
} |
| 786 |
} |
802 |
} |