protected TypeBinding getTypeBinding(Scope scope) {
    // it can be a package, type or member type
    Binding binding = scope.parent.getTypeOrPackage(this.tokens); // step up from the ClassScope
    if (!binding.isValidBinding()) {
      scope.problemReporter().invalidType(this, (TypeBinding) binding);

      if (binding.problemId() == ProblemReasons.NotFound) {
        throw new CompletionNodeFound(this, binding, scope);
      }

      throw new CompletionNodeFound();
    }

    throw new CompletionNodeFound(this, binding, scope);
  }
 /**
  * Resolve selected node if not null and throw exception to let clients know that it has been
  * found.
  *
  * @throws SelectionNodeFound
  */
 private void internalResolve(Scope scope) {
   if (this.selectedNode != null) {
     switch (scope.kind) {
       case Scope.CLASS_SCOPE:
         this.selectedNode.resolveType((ClassScope) scope);
         break;
       case Scope.METHOD_SCOPE:
         this.selectedNode.resolveType((MethodScope) scope);
         break;
     }
     Binding binding = null;
     if (this.selectedNode instanceof JavadocFieldReference) {
       JavadocFieldReference fieldRef = (JavadocFieldReference) this.selectedNode;
       binding = fieldRef.binding;
       if (binding == null && fieldRef.methodBinding != null) {
         binding = fieldRef.methodBinding;
       }
     } else if (this.selectedNode instanceof JavadocMessageSend) {
       binding = ((JavadocMessageSend) this.selectedNode).binding;
     } else if (this.selectedNode instanceof JavadocAllocationExpression) {
       binding = ((JavadocAllocationExpression) this.selectedNode).binding;
     } else if (this.selectedNode instanceof JavadocSingleNameReference) {
       binding = ((JavadocSingleNameReference) this.selectedNode).binding;
     } else if (this.selectedNode instanceof JavadocSingleTypeReference) {
       JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) this.selectedNode;
       if (typeRef.packageBinding == null) {
         binding = typeRef.resolvedType;
       }
     } else if (this.selectedNode instanceof JavadocQualifiedTypeReference) {
       JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) this.selectedNode;
       if (typeRef.packageBinding == null) {
         binding = typeRef.resolvedType;
       }
     } else {
       binding = this.selectedNode.resolvedType;
     }
     throw new SelectionNodeFound(binding);
   } else if (this.inheritDocSelected) {
     // no selection node when inheritDoc tag is selected
     // But we need to detect it to enable code select on inheritDoc
     ReferenceContext referenceContext = scope.referenceContext();
     if (referenceContext instanceof MethodDeclaration) {
       throw new SelectionNodeFound(((MethodDeclaration) referenceContext).binding);
     }
   }
 }
 public boolean checkUnsafeCast(
     Scope scope,
     TypeBinding castType,
     TypeBinding expressionType,
     TypeBinding match,
     boolean isNarrowing) {
   if (TypeBinding.equalsEquals(match, castType)) {
     if (!isNarrowing
         && TypeBinding.equalsEquals(
             match,
             this.resolvedType
                 .leafComponentType()) // do not tag as unnecessary when recursing through upper
         // bounds
         && !(expressionType.isParameterizedType()
             && expressionType.isProvablyDistinct(castType))) {
       tagAsUnnecessaryCast(scope, castType);
     }
     return true;
   }
   if (match != null) {
     if (isNarrowing
         ? match.isProvablyDistinct(expressionType)
         : castType.isProvablyDistinct(match)) {
       return false;
     }
   }
   switch (castType.kind()) {
     case Binding.PARAMETERIZED_TYPE:
       if (!castType.isReifiable()) {
         if (match == null) { // unrelated types
           this.bits |= ASTNode.UnsafeCast;
           return true;
         }
         switch (match.kind()) {
           case Binding.PARAMETERIZED_TYPE:
             if (isNarrowing) {
               // [JLS 5.5] T <: S
               if (expressionType.isRawType() || !expressionType.isEquivalentTo(match)) {
                 this.bits |= ASTNode.UnsafeCast;
                 return true;
               }
               // [JLS 5.5] S has no subtype X != T, such that |X| == |T|
               // if I2<T,U> extends I1<T>, then cast from I1<T> to I2<T,U> is unchecked
               ParameterizedTypeBinding paramCastType = (ParameterizedTypeBinding) castType;
               ParameterizedTypeBinding paramMatch = (ParameterizedTypeBinding) match;
               // easy case if less parameters on match
               TypeBinding[] castArguments = paramCastType.arguments;
               int length = castArguments == null ? 0 : castArguments.length;
               if (paramMatch.arguments == null || length > paramMatch.arguments.length) {
                 this.bits |= ASTNode.UnsafeCast;
               } else if ((paramCastType.tagBits
                       & (TagBits.HasDirectWildcard | TagBits.HasTypeVariable))
                   != 0) {
                 // verify alternate cast type, substituting different type arguments
                 nextAlternateArgument:
                 for (int i = 0; i < length; i++) {
                   switch (castArguments[i].kind()) {
                     case Binding.WILDCARD_TYPE:
                     case Binding.TYPE_PARAMETER:
                       break; // check substituting with other
                     default:
                       continue nextAlternateArgument; // no alternative possible
                   }
                   TypeBinding[] alternateArguments;
                   // need to clone for each iteration to avoid env paramtype cache interference
                   System.arraycopy(
                       paramCastType.arguments,
                       0,
                       alternateArguments = new TypeBinding[length],
                       0,
                       length);
                   alternateArguments[i] = scope.getJavaLangObject();
                   LookupEnvironment environment = scope.environment();
                   ParameterizedTypeBinding alternateCastType =
                       environment.createParameterizedType(
                           (ReferenceBinding) castType.erasure(),
                           alternateArguments,
                           castType.enclosingType());
                   if (TypeBinding.equalsEquals(
                       alternateCastType.findSuperTypeOriginatingFrom(expressionType), match)) {
                     this.bits |= ASTNode.UnsafeCast;
                     break;
                   }
                 }
               }
               return true;
             } else {
               // [JLS 5.5] T >: S
               if (!match.isEquivalentTo(castType)) {
                 this.bits |= ASTNode.UnsafeCast;
                 return true;
               }
             }
             break;
           case Binding.RAW_TYPE:
             this.bits |=
                 ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
             return true;
           default:
             if (isNarrowing) {
               // match is not parameterized or raw, then any other subtype of match will erase  to
               // |T|
               this.bits |= ASTNode.UnsafeCast;
               return true;
             }
             break;
         }
       }
       break;
     case Binding.ARRAY_TYPE:
       TypeBinding leafType = castType.leafComponentType();
       if (isNarrowing && (!leafType.isReifiable() || leafType.isTypeVariable())) {
         this.bits |= ASTNode.UnsafeCast;
         return true;
       }
       break;
     case Binding.TYPE_PARAMETER:
       this.bits |= ASTNode.UnsafeCast;
       return true;
       //		(disabled) https://bugs.eclipse.org/bugs/show_bug.cgi?id=240807
       //		case Binding.TYPE :
       //			if (isNarrowing && match == null && expressionType.isParameterizedType()) {
       //				this.bits |= ASTNode.UnsafeCast;
       //				return true;
       //			}
       //			break;
   }
   if (!isNarrowing
       && TypeBinding.equalsEquals(
           match,
           this.resolvedType
               .leafComponentType())) { // do not tag as unnecessary when recursing through upper
     // bounds
     tagAsUnnecessaryCast(scope, castType);
   }
   return true;
 }