public List<? extends TypeMirror> getParameterTypes() { MethodBinding binding = (MethodBinding) this._binding; TypeBinding[] parameters = binding.parameters; int length = parameters.length; boolean isEnumConstructor = binding.isConstructor() && binding.declaringClass.isEnum() && binding.declaringClass.isBinaryBinding() && ((binding.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0); if (isEnumConstructor) { if (length == 2) { return Collections.emptyList(); } ArrayList<TypeMirror> list = new ArrayList<TypeMirror>(); for (int i = 2; i < length; i++) { list.add(_env.getFactory().newTypeMirror(parameters[i])); } return Collections.unmodifiableList(list); } if (length != 0) { ArrayList<TypeMirror> list = new ArrayList<TypeMirror>(); for (TypeBinding typeBinding : parameters) { list.add(_env.getFactory().newTypeMirror(typeBinding)); } return Collections.unmodifiableList(list); } return Collections.emptyList(); }
/** * In this case: check match of "replace" and "callin" flags, plus static-ness * * @param haveBaseMethods have base methods been resolved? * @param baseClass the role's bound base class */ @Override protected void checkModifiers(boolean haveBaseMethods, ReferenceBinding baseClass) { if (this.ignoreFurtherInvestigation) // error was already flagged, i.e. missing replace return; // replace and callin matching: if (isReplaceCallin()) { if (!this.roleMethodSpec.resolvedMethod.isCallin()) { this.scope .problemReporter() .replaceMappingToNonCallin(this.roleMethodSpec, this.roleMethodSpec.resolvedMethod); this.binding.tagBits |= TagBits.HasMappingIncompatibility; return; } } else { if (this.roleMethodSpec.resolvedMethod.isCallin()) { this.scope.problemReporter().callinMethodBoundNonReplace(this.roleMethodSpec, this); this.binding.tagBits |= TagBits.HasMappingIncompatibility; return; } } if (haveBaseMethods) { // static non-static consistency: if (!this.roleMethodSpec.resolvedMethod.isStatic()) { for (int i = 0; i < this.baseMethodSpecs.length; i++) { this.baseMethodSpecs[i].checkStaticness(this, false); } } if (isReplaceCallin()) { if (this.roleMethodSpec.resolvedMethod.isStatic()) { for (int i = 0; i < this.baseMethodSpecs.length; i++) { this.baseMethodSpecs[i].checkStaticness(this, true); } } } // callin-to-final? respect OTJLD 4.1(f) for (int i = 0; i < this.baseMethodSpecs.length; i++) { MethodBinding baseMethod = this.baseMethodSpecs[i].resolvedMethod; if (baseMethod != null) { if (baseMethod.isFinal()) { if (TypeBinding.notEquals(baseMethod.declaringClass, baseClass)) { this.scope .problemReporter() .bindingToInheritedFinal(this.baseMethodSpecs[i], baseMethod, baseClass); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } } if (baseMethod.isConstructor()) { if (this.callinModifier != TokenNameafter) { this.scope .problemReporter() .callinToCtorMustBeAfter(this.baseMethodSpecs[i], baseMethod); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } } } } } }
private MethodBinding checkAndResolveMethodRef( SourceInfo errorInfo, ReferenceBinding clazz, JsniRef jsniRef, boolean hasQualifier, boolean isLvalue) { assert jsniRef.isMethod(); List<MethodBinding> targets = getMatchingMethods(clazz, jsniRef); if (targets.size() > 1) { emitError( ERR_AMBIGUOUS_WILDCARD_MATCH, errorInfo, jsniRef, JdtUtil.formatBinding(targets.get(0)), JdtUtil.formatBinding(targets.get(1))); return null; } else if (targets.isEmpty()) { emitError(ERR_UNABLE_TO_RESOLVE_METHOD, errorInfo, jsniRef); return null; } MethodBinding target = targets.get(0); resolveJsniRef(jsniRef, target); if (target.isDeprecated() && !isEnclosingClass(method.binding.declaringClass, target.declaringClass)) { emitWarning("deprecation", WARN_DEPRECATED_METHOD, errorInfo, jsniRef); } if (isLvalue) { emitError(ERR_ILLEGAL_ASSIGNMENT_TO_METHOD, errorInfo, jsniRef); } boolean needsQualifer = !target.isStatic() && !target.isConstructor(); if (!needsQualifer && hasQualifier) { emitError(ERR_UNNECESSARY_QUALIFIER_STATIC_METHOD, errorInfo, jsniRef); } else if (needsQualifer && !hasQualifier) { emitError(ERR_MISSING_QUALIFIER_INSTANCE_METHOD, errorInfo, jsniRef); } if (hasUnsafeLongsAnnotation) { return target; } if (containsLong(target.returnType)) { emitError(ERR_ILLEGAL_RETURN_TYPE, errorInfo, jsniRef, typeString(target.returnType)); } if (target.parameters != null) { int i = 0; for (TypeBinding paramType : target.parameters) { ++i; if (containsLong(paramType)) { // It would be nice to print the parameter name, but how to find it? emitError(ERR_ILLEGAL_PARAMETER, errorInfo, jsniRef, i, typeString(paramType)); } } } return target; }
/* * @see ITypeBinding#getDeclaredMethods() */ public synchronized IMethodBinding[] getDeclaredMethods() { if (this.methods != null) { return this.methods; } try { if (isClass() || isInterface() || isEnum()) { ReferenceBinding referenceBinding = (ReferenceBinding) this.binding; org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient int length = internalMethods.length; if (length != 0) { int convertedMethodCount = 0; IMethodBinding[] newMethods = new IMethodBinding[length]; for (int i = 0; i < length; i++) { org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i]; if (methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface())) { continue; } IMethodBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding); if (methodBinding2 != null) { newMethods[convertedMethodCount++] = methodBinding2; } } if (convertedMethodCount != length) { if (convertedMethodCount == 0) { return this.methods = NO_METHOD_BINDINGS; } System.arraycopy( newMethods, 0, (newMethods = new IMethodBinding[convertedMethodCount]), 0, convertedMethodCount); } return this.methods = newMethods; } } } catch (RuntimeException e) { /* in case a method cannot be resolvable due to missing jars on the classpath * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299 */ org.eclipse.jdt.internal.core.util.Util.log( e, "Could not retrieve declared methods"); // $NON-NLS-1$ } return this.methods = NO_METHOD_BINDINGS; }
private void searchVisibleLocalMethods( MethodBinding[] methods, ReferenceBinding receiverType, Scope scope, InvocationSite invocationSite, Scope invocationScope, boolean onlyStaticMethods, ObjectVector methodsFound) { ObjectVector newMethodsFound = new ObjectVector(); // Inherited methods which are hidden by subclasses are filtered out // No visibility checks can be performed without the scope & invocationSite next: for (int f = methods.length; --f >= 0; ) { MethodBinding method = methods[f]; if (method.isSynthetic()) continue next; if (method.isDefaultAbstract()) continue next; if (method.isConstructor()) continue next; if (onlyStaticMethods && !method.isStatic()) continue next; if (!method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; for (int i = methodsFound.size; --i >= 0; ) { MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i); if (method == otherMethod) continue next; if (CharOperation.equals(method.selector, otherMethod.selector, true)) { if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { continue next; } } } newMethodsFound.add(method); } methodsFound.addAll(newMethodsFound); }
private static void checkAlternateBinding( BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) { InvocationSite fakeInvocationSite = new InvocationSite() { public TypeBinding[] genericTypeArguments() { return null; } public boolean isSuperAccess() { return invocationSite.isSuperAccess(); } public boolean isTypeAccess() { return invocationSite.isTypeAccess(); } public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */ } public void setDepth(int depth) { /* ignore */ } public void setFieldIndex(int depth) { /* ignore */ } public int sourceStart() { return 0; } public int sourceEnd() { return 0; } }; MethodBinding bindingIfNoCast; if (binding.isConstructor()) { bindingIfNoCast = scope.getConstructor( (ReferenceBinding) receiverType, alternateArgumentTypes, fakeInvocationSite); } else { bindingIfNoCast = receiver.isImplicitThis() ? scope.getImplicitMethod( binding.selector, alternateArgumentTypes, fakeInvocationSite) : scope.getMethod( receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite); } if (bindingIfNoCast == binding) { int argumentLength = originalArgumentTypes.length; if (binding.isVarargs()) { int paramLength = binding.parameters.length; if (paramLength == argumentLength) { int varargsIndex = paramLength - 1; ArrayBinding varargsType = (ArrayBinding) binding.parameters[varargsIndex]; TypeBinding lastArgType = alternateArgumentTypes[varargsIndex]; // originalType may be compatible already, but cast mandated // to clarify between varargs/non-varargs call if (varargsType.dimensions != lastArgType.dimensions()) { return; } if (lastArgType.isCompatibleWith(varargsType.elementsType()) && lastArgType.isCompatibleWith(varargsType)) { return; } } } for (int i = 0; i < argumentLength; i++) { if (originalArgumentTypes[i] != alternateArgumentTypes[i]) { scope.problemReporter().unnecessaryCast((CastExpression) arguments[i]); } } } }
/** Locate declaration in the current class file. This class file is always in a jar. */ public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info) throws CoreException { SearchPattern pattern = locator.pattern; // check annotations references matchAnnotations(pattern, locator, classFile, info); // check class definition BinaryType binaryType = (BinaryType) classFile.getType(); if (matchBinary(pattern, info, null)) { binaryType = new ResolvedBinaryType( (JavaElement) binaryType.getParent(), binaryType.getElementName(), binaryType.getKey()); locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE); return; } // Define arrays to store methods/fields from binary type if necessary IBinaryMethod[] binaryMethods = info.getMethods(); int bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length; IBinaryMethod[] unresolvedMethods = null; char[][] binaryMethodSignatures = null; boolean hasUnresolvedMethods = false; // Get fields from binary type info IBinaryField[] binaryFields = info.getFields(); int bFieldsLength = binaryFields == null ? 0 : binaryFields.length; IBinaryField[] unresolvedFields = null; boolean hasUnresolvedFields = false; // Report as many accurate matches as possible int accuracy = SearchMatch.A_ACCURATE; boolean mustResolve = pattern.mustResolve; if (mustResolve) { BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info); if (binding != null) { // filter out element not in hierarchy scope if (!locator.typeInHierarchy(binding)) return; // Search matches on resolved methods MethodBinding[] availableMethods = binding.availableMethods(); int aMethodsLength = availableMethods == null ? 0 : availableMethods.length; hasUnresolvedMethods = bMethodsLength != aMethodsLength; for (int i = 0; i < aMethodsLength; i++) { MethodBinding method = availableMethods[i]; char[] methodSignature = method.genericSignature(); if (methodSignature == null) methodSignature = method.signature(); // Report the match if possible int level = locator.patternLocator.resolveLevel(method); if (level != PatternLocator.IMPOSSIBLE_MATCH) { IMethod methodHandle = binaryType.getMethod( new String( method.isConstructor() ? binding.compoundName[binding.compoundName.length - 1] : method.selector), CharOperation.toStrings( Signature.getParameterTypes(convertClassFileFormat(methodSignature)))); accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE; locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, accuracy); } // Remove method from unresolved list if (hasUnresolvedMethods) { if (binaryMethodSignatures == null) { // Store binary method signatures to avoid multiple computation binaryMethodSignatures = new char[bMethodsLength][]; for (int j = 0; j < bMethodsLength; j++) { IBinaryMethod binaryMethod = binaryMethods[j]; char[] signature = binaryMethod.getGenericSignature(); if (signature == null) signature = binaryMethod.getMethodDescriptor(); binaryMethodSignatures[j] = signature; } } for (int j = 0; j < bMethodsLength; j++) { if (CharOperation.equals(binaryMethods[j].getSelector(), method.selector) && CharOperation.equals(binaryMethodSignatures[j], methodSignature)) { if (unresolvedMethods == null) { System.arraycopy( binaryMethods, 0, unresolvedMethods = new IBinaryMethod[bMethodsLength], 0, bMethodsLength); } unresolvedMethods[j] = null; break; } } } } // Search matches on resolved fields FieldBinding[] availableFields = binding.availableFields(); int aFieldsLength = availableFields == null ? 0 : availableFields.length; hasUnresolvedFields = bFieldsLength != aFieldsLength; for (int i = 0; i < aFieldsLength; i++) { FieldBinding field = availableFields[i]; // Report the match if possible int level = locator.patternLocator.resolveLevel(field); if (level != PatternLocator.IMPOSSIBLE_MATCH) { IField fieldHandle = binaryType.getField(new String(field.name)); accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE; locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, accuracy); } // Remove the field from unresolved list if (hasUnresolvedFields) { for (int j = 0; j < bFieldsLength; j++) { if (CharOperation.equals(binaryFields[j].getName(), field.name)) { if (unresolvedFields == null) { System.arraycopy( binaryFields, 0, unresolvedFields = new IBinaryField[bFieldsLength], 0, bFieldsLength); } unresolvedFields[j] = null; break; } } } } // If all methods/fields were accurate then returns now if (!hasUnresolvedMethods && !hasUnresolvedFields) { return; } } accuracy = SearchMatch.A_INACCURATE; } // Report inaccurate methods if (mustResolve) binaryMethods = unresolvedMethods; bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length; for (int i = 0; i < bMethodsLength; i++) { IBinaryMethod method = binaryMethods[i]; if (method == null) continue; // impossible match or already reported as accurate if (matchBinary(pattern, method, info)) { char[] name; if (method.isConstructor()) { name = info.getName(); int lastSlash = CharOperation.lastIndexOf('/', name); if (lastSlash != -1) { name = CharOperation.subarray(name, lastSlash + 1, name.length); } } else { name = method.getSelector(); } String selector = new String(name); char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i]; if (methodSignature == null) { methodSignature = method.getGenericSignature(); if (methodSignature == null) methodSignature = method.getMethodDescriptor(); } String[] parameterTypes = CharOperation.toStrings( Signature.getParameterTypes(convertClassFileFormat(methodSignature))); IMethod methodHandle = binaryType.getMethod(selector, parameterTypes); methodHandle = new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey()); locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy); } } // Report inaccurate fields if (mustResolve) binaryFields = unresolvedFields; bFieldsLength = binaryFields == null ? 0 : binaryFields.length; for (int i = 0; i < bFieldsLength; i++) { IBinaryField field = binaryFields[i]; if (field == null) continue; // impossible match or already reported as accurate if (matchBinary(pattern, field, info)) { String fieldName = new String(field.getName()); IField fieldHandle = binaryType.getField(fieldName); fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey()); locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy); } } }
private JavaElement getUnresolvedJavaElement() { IType declaringType = (IType) getDeclaringClass().getJavaElement(); if (declaringType == null) return null; if (!(this.resolver instanceof DefaultBindingResolver)) return null; ASTNode node = (ASTNode) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this); if (node != null && declaringType.getParent().getElementType() != IJavaElement.CLASS_FILE) { if (node instanceof MethodDeclaration) { MethodDeclaration methodDeclaration = (MethodDeclaration) node; ArrayList parameterSignatures = new ArrayList(); Iterator iterator = methodDeclaration.parameters().iterator(); while (iterator.hasNext()) { SingleVariableDeclaration parameter = (SingleVariableDeclaration) iterator.next(); Type type = parameter.getType(); String typeSig = Util.getSignature(type); int arrayDim = parameter.getExtraDimensions(); if (parameter.getAST().apiLevel() >= AST.JLS3 && parameter.isVarargs()) { arrayDim++; } if (arrayDim > 0) { typeSig = Signature.createArraySignature(typeSig, arrayDim); } parameterSignatures.add(typeSig); } int parameterCount = parameterSignatures.size(); String[] parameters = new String[parameterCount]; parameterSignatures.toArray(parameters); return (JavaElement) declaringType.getMethod(getName(), parameters); } else { // annotation type member declaration AnnotationTypeMemberDeclaration typeMemberDeclaration = (AnnotationTypeMemberDeclaration) node; return (JavaElement) declaringType.getMethod( typeMemberDeclaration.getName().getIdentifier(), new String[0]); // annotation type members don't have parameters } } else { // case of method not in the created AST, or a binary method org.eclipse.jdt.internal.compiler.lookup.MethodBinding original = this.binding.original(); String selector = original.isConstructor() ? declaringType.getElementName() : new String(original.selector); TypeBinding[] parameters = original.parameters; int length = parameters == null ? 0 : parameters.length; String[] parameterSignatures = new String[length]; for (int i = 0; i < length; i++) { parameterSignatures[i] = new String(parameters[i].genericTypeSignature()).replace('/', '.'); } IMethod result = declaringType.getMethod(selector, parameterSignatures); if (declaringType.isBinary()) return (JavaElement) result; IMethod[] methods = null; try { methods = declaringType.getMethods(); } catch (JavaModelException e) { // declaring type doesn't exist return null; } IMethod[] candidates = Member.findMethods(result, methods); if (candidates == null || candidates.length == 0) return null; return (JavaElement) candidates[0]; } }