List of usage examples for org.eclipse.jdt.internal.compiler.lookup ProblemBinding ProblemBinding
ProblemBinding(char[] name, ReferenceBinding searchType, int problemId)
From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java
License:Open Source License
public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; try {/* w w w .ja v a2 s. co m*/ env.missingClassFileLocation = invocationSite; Binding binding = null; FieldBinding problemField = null; if ((mask & Binding.VARIABLE) != 0) { boolean insideStaticContext = false; boolean insideConstructorCall = false; boolean insideTypeAnnotation = false; FieldBinding foundField = null; // can be a problem field which is answered if a valid field is not found ProblemFieldBinding foundInsideProblem = null; // inside Constructor call or inside static context Scope scope = this; int depth = 0; int foundDepth = 0; ReferenceBinding foundActualReceiverType = null; done: while (true) { // done when a COMPILATION_UNIT_SCOPE is found switch (scope.kind) { case METHOD_SCOPE: MethodScope methodScope = (MethodScope) scope; insideStaticContext |= methodScope.isStatic; insideConstructorCall |= methodScope.isConstructorCall; insideTypeAnnotation = methodScope.insideTypeAnnotation; //$FALL-THROUGH$ could duplicate the code below to save a cast - questionable optimization case BLOCK_SCOPE: LocalVariableBinding variableBinding = scope.findVariable(name); // looks in this scope only if (variableBinding != null) { if (foundField != null && foundField.isValidBinding()) return new ProblemFieldBinding(foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); if (depth > 0) invocationSite.setDepth(depth); return variableBinding; } break; case CLASS_SCOPE: ClassScope classScope = (ClassScope) scope; ReferenceBinding receiverType = classScope.enclosingReceiverType(); if (!insideTypeAnnotation) { FieldBinding fieldBinding = classScope.findField(receiverType, name, invocationSite, needResolve); // Use next line instead if willing to enable protected access accross inner types // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite); if (fieldBinding != null) { // skip it if we did not find anything if (fieldBinding.problemId() == ProblemReasons.Ambiguous) { if (foundField == null || foundField.problemId() == ProblemReasons.NotVisible) // supercedes any potential InheritedNameHidesEnclosingName problem return fieldBinding; // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead) return new ProblemFieldBinding(foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); } ProblemFieldBinding insideProblem = null; if (fieldBinding.isValidBinding()) { if (!fieldBinding.isStatic()) { if (insideConstructorCall) { insideProblem = new ProblemFieldBinding(fieldBinding, // closest match fieldBinding.declaringClass, name, ProblemReasons.NonStaticReferenceInConstructorInvocation); } else if (insideStaticContext) { insideProblem = new ProblemFieldBinding(fieldBinding, // closest match fieldBinding.declaringClass, name, ProblemReasons.NonStaticReferenceInStaticContext); } } if (receiverType == fieldBinding.declaringClass || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { // found a valid field in the 'immediate' scope (i.e. not inherited) // OR in 1.4 mode (inherited shadows enclosing) if (foundField == null) { if (depth > 0) { invocationSite.setDepth(depth); invocationSite.setActualReceiverType(receiverType); } // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited) return insideProblem == null ? fieldBinding : insideProblem; } if (foundField.isValidBinding()) // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited) // but only if "valid field" was inherited in the first place. if (foundField.declaringClass != fieldBinding.declaringClass && foundField.declaringClass != foundActualReceiverType) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=316956 // i.e. have we found the same field - do not trust field identity yet return new ProblemFieldBinding(foundField, // closest match foundField.declaringClass, name, ProblemReasons.InheritedNameHidesEnclosingName); } } if (foundField == null || (foundField.problemId() == ProblemReasons.NotVisible && fieldBinding.problemId() != ProblemReasons.NotVisible)) { // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is... foundDepth = depth; foundActualReceiverType = receiverType; foundInsideProblem = insideProblem; foundField = fieldBinding; } } } insideTypeAnnotation = false; depth++; insideStaticContext |= receiverType.isStatic(); // 1EX5I8Z - accessing outer fields within a constructor call is permitted // in order to do so, we change the flag as we exit from the type, not the method // itself, because the class scope is used to retrieve the fields. MethodScope enclosingMethodScope = scope.methodScope(); insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall; break; case COMPILATION_UNIT_SCOPE: break done; } scope = scope.parent; } if (foundInsideProblem != null) return foundInsideProblem; if (foundField != null) { if (foundField.isValidBinding()) { if (foundDepth > 0) { invocationSite.setDepth(foundDepth); invocationSite.setActualReceiverType(foundActualReceiverType); } return foundField; } problemField = foundField; foundField = null; } if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // at this point the scope is a compilation unit scope & need to check for imported static fields unitScope.faultInImports(); // ensure static imports are resolved ImportBinding[] imports = unitScope.imports; if (imports != null) { // check single static imports for (int i = 0, length = imports.length; i < length; i++) { ImportBinding importBinding = imports[i]; if (importBinding.isStatic() && !importBinding.onDemand) { if (CharOperation.equals( importBinding.compoundName[importBinding.compoundName.length - 1], name)) { if (unitScope.resolveSingleImport(importBinding, Binding.TYPE | Binding.FIELD | Binding.METHOD) != null && importBinding.resolvedImport instanceof FieldBinding) { foundField = (FieldBinding) importBinding.resolvedImport; ImportReference importReference = importBinding.reference; if (importReference != null && needResolve) { importReference.bits |= ASTNode.Used; } invocationSite.setActualReceiverType(foundField.declaringClass); if (foundField.isValidBinding()) { return foundField; } if (problemField == null) problemField = foundField; } } } } // check on demand imports boolean foundInImport = false; for (int i = 0, length = imports.length; i < length; i++) { ImportBinding importBinding = imports[i]; if (importBinding.isStatic() && importBinding.onDemand) { Binding resolvedImport = importBinding.resolvedImport; if (resolvedImport instanceof ReferenceBinding) { FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve); if (temp != null) { if (!temp.isValidBinding()) { if (problemField == null) problemField = temp; } else if (temp.isStatic()) { if (foundField == temp) continue; ImportReference importReference = importBinding.reference; if (importReference != null && needResolve) { importReference.bits |= ASTNode.Used; } if (foundInImport) // Answer error binding -- import on demand conflict; name found in two import on demand packages. return new ProblemFieldBinding(foundField, // closest match foundField.declaringClass, name, ProblemReasons.Ambiguous); foundField = temp; foundInImport = true; } } } } } if (foundField != null) { invocationSite.setActualReceiverType(foundField.declaringClass); return foundField; } } } } // We did not find a local or instance variable. if ((mask & Binding.TYPE) != 0) { if ((binding = getBaseType(name)) != null) return binding; binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE, needResolve); if (binding.isValidBinding() || mask == Binding.TYPE) return binding; // answer the problem type binding if we are only looking for a type } else if ((mask & Binding.PACKAGE) != 0) { unitScope.recordSimpleReference(name); if ((binding = env.getTopLevelPackage(name)) != null) return binding; } if (problemField != null) return problemField; if (binding != null && binding.problemId() != ProblemReasons.NotFound) return binding; // answer the better problem binding return new ProblemBinding(name, enclosingSourceType(), ProblemReasons.NotFound); } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; } finally { env.missingClassFileLocation = null; } }