public void resolveJavadoc() {

    if (this.binding == null) return;
    if (this.javadoc != null) {
      this.javadoc.resolve(this.scope);
      return;
    }
    if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
      // Set javadoc visibility
      int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
      ClassScope classScope = this.scope.classScope();
      ProblemReporter reporter = this.scope.problemReporter();
      int severity = reporter.computeSeverity(IProblem.JavadocMissing);
      if (severity != ProblemSeverities.Ignore) {
        if (classScope != null) {
          javadocVisibility =
              Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility);
        }
        int javadocModifiers =
            (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK)
                | javadocVisibility;
        reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers);
      }
    }
  }
  /** Perform deferred check specific to parameterized types: bound checks, supertype collisions */
  public void checkParameterizedTypes() { // AspectJ Extension - raised to public
    if (compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) return;

    for (int i = 0, length = this.topLevelTypes.length; i < length; i++) {
      ClassScope scope = this.topLevelTypes[i].scope;
      scope.checkParameterizedTypeBounds();
      scope.checkParameterizedSuperTypeCollisions();
    }
  }
  /*
   * Remembers all type bindings defined in the given parsed unit, adding local/anonymous types if specified.
   */
  private void rememberAllTypes(
      CompilationUnitDeclaration parsedUnit,
      org.aspectj.org.eclipse.jdt.core.ICompilationUnit cu,
      boolean includeLocalTypes) {
    TypeDeclaration[] types = parsedUnit.types;
    if (types != null) {
      for (int i = 0, length = types.length; i < length; i++) {
        TypeDeclaration type = types[i];
        rememberWithMemberTypes(type, cu.getType(new String(type.name)));
      }
    }
    if (!includeLocalTypes
        || (parsedUnit.localTypes == null && parsedUnit.functionalExpressions == null)) return;

    HandleFactory factory = new HandleFactory();
    HashSet existingElements =
        new HashSet(parsedUnit.localTypeCount + parsedUnit.functionalExpressionsCount);
    HashMap knownScopes =
        new HashMap(parsedUnit.localTypeCount + parsedUnit.functionalExpressionsCount);

    if (parsedUnit.localTypes != null) {
      for (int i = 0; i < parsedUnit.localTypeCount; i++) {
        LocalTypeBinding localType = parsedUnit.localTypes[i];
        ClassScope classScope = localType.scope;
        TypeDeclaration typeDecl = classScope.referenceType();
        IType typeHandle =
            (IType) factory.createElement(classScope, cu, existingElements, knownScopes);
        rememberWithMemberTypes(typeDecl, typeHandle);
      }
    }
    if (parsedUnit.functionalExpressions != null) {
      for (int i = 0; i < parsedUnit.functionalExpressionsCount; i++) {
        if (parsedUnit.functionalExpressions[i] instanceof LambdaExpression) {
          final LambdaExpression expression =
              (LambdaExpression) parsedUnit.functionalExpressions[i];
          if (expression.resolvedType != null && expression.resolvedType.isValidBinding()) {
            IType typeHandle =
                (IType)
                    factory.createLambdaTypeElement(expression, cu, existingElements, knownScopes);
            remember(typeHandle, expression.getTypeBinding());
          }
        }
      }
    }
  }
 @Override
 public MethodTypeWrapper GetMethod(String method) throws TypingRuleException {
   MethodTypeWrapper resultMethod;
   if (!(fatherScope instanceof ClassScope)) {
     throw new Error("Internal error, method scope cann't be nested not in class scope");
   }
   ClassScope classScope = (ClassScope) fatherScope;
   // if (classScope.getStaticMethodScopes().containsKey(method))
   // {
   // return classScope.getStaticMethodScopes().get(method);
   // }
   resultMethod = classScope.getStaticMethod(method);
   if (resultMethod != null) return resultMethod;
   resultMethod = classScope.getVirtualMethod(method);
   if (resultMethod != null) {
     if (methodType.equals(MethodType.Static)) {
       throw new TypingRuleException(
           "Calling a local virtual method from inside a static method is not allowed", -1);
     }
     return resultMethod;
   }
   return fatherScope.GetMethod(method);
 }
  @Override
  public Type GetVariable(String name) {

    // search parameters
    Type resultType = parameters.get(name);
    // search local vars
    if (resultType == null) {
      resultType = super.GetVariable(name);
    }

    if (resultType == null) {
      // search fields
      Scope currentScope = fatherScope;
      while (!(currentScope instanceof ClassScope)) currentScope = fatherScope;
      ClassScope classScope = (ClassScope) currentScope;
      resultType = classScope.getField(name);
      if (resultType != null && methodType.equals(MethodType.Static)) {
        throw new TypingRuleException("Use of field inside a static method is not allowed", -1);
      }
      // while (currentScope instanceof ClassScope) {
      // ClassScope classScope = (ClassScope) currentScope;
      // if (classScope.getFields().containsKey(name)) {
      // if (methodType.equals(MethodType.Static)) {
      // throw new TypingRuleException(
      // "Use of field inside a static method is not allowed",
      // -1);
      // }
      // if (methodType.equals(MethodType.Virtual)) {
      // resultType = classScope.getFields().get(name);
      // }
      // }
      // currentScope = currentScope.fatherScope;
    }

    return resultType;
  }
  void write(ClassScope scope, Method method, TextOutput out) {
    MethodHandler.writeMethodDeclarationJava(out, method, paramNames);
    out.openBlock();
    out.append("return ");
    if (isList) {
      out.append("readObjectArray(")
          .append(Util.READER_NAME)
          .append(", null, new ")
          .append(scope.requireFactoryGenerationAndGetName(typeHandler))
          .append(Util.TYPE_FACTORY_NAME_POSTFIX)
          .append("()")
          .append(", false)");
    } else {
      typeHandler.writeInstantiateCode(scope, out);
      out.append('(').append(Util.READER_NAME);
      out.comma().space();
      out.append(paramNames.size() == 1 ? "null" : "nextName");
      out.append(')');
    }
    out.semi();

    out.closeBlock();
  }
  void buildTypeBindings(AccessRestriction accessRestriction) {
    this.topLevelTypes =
        new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
    boolean firstIsSynthetic = false;
    if (this.referenceContext.compilationResult.compilationUnit != null) {
      char[][] expectedPackageName =
          this.referenceContext.compilationResult.compilationUnit.getPackageName();
      if (expectedPackageName != null
          && !CharOperation.equals(this.currentPackageName, expectedPackageName)) {

        // only report if the unit isn't structurally empty
        if (this.referenceContext.currentPackage != null
            || this.referenceContext.types != null
            || this.referenceContext.imports != null) {
          problemReporter().packageIsNotExpectedPackage(this.referenceContext);
        }
        this.currentPackageName =
            expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR : expectedPackageName;
      }
    }
    if (this.currentPackageName == CharOperation.NO_CHAR_CHAR) {
      // environment default package is never null
      this.fPackage = this.environment.defaultPackage;
    } else {
      if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) {
        if (this.referenceContext.currentPackage != null) {
          problemReporter()
              .packageCollidesWithType(
                  this.referenceContext); // only report when the unit has a package statement
        }
        // ensure fPackage is not null
        this.fPackage = this.environment.defaultPackage;
        return;
      } else if (this.referenceContext.isPackageInfo()) {
        // resolve package annotations now if this is "package-info.java".
        if (this.referenceContext.types == null || this.referenceContext.types.length == 0) {
          this.referenceContext.types = new TypeDeclaration[1];
          this.referenceContext.createPackageInfoType();
          firstIsSynthetic = true;
        }
        // ensure the package annotations are copied over before resolution
        if (this.referenceContext.currentPackage != null
            && this.referenceContext.currentPackage.annotations != null) {
          this.referenceContext.types[0].annotations =
              this.referenceContext.currentPackage.annotations;
        }
      }
      recordQualifiedReference(this.currentPackageName); // always dependent on your own package
    }

    // Skip typeDeclarations which know of previously reported errors
    TypeDeclaration[] types = this.referenceContext.types;
    int typeLength = (types == null) ? 0 : types.length;
    this.topLevelTypes = new SourceTypeBinding[typeLength];
    int count = 0;
    nextType:
    for (int i = 0; i < typeLength; i++) {
      TypeDeclaration typeDecl = types[i];
      if (this.environment.isProcessingAnnotations && this.environment.isMissingType(typeDecl.name))
        throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the
      // type
      ReferenceBinding typeBinding = this.fPackage.getType0(typeDecl.name);
      recordSimpleReference(typeDecl.name); // needed to detect collision cases
      if (typeBinding != null
          && typeBinding.isValidBinding()
          && !(typeBinding instanceof UnresolvedReferenceBinding)) {
        // if its an unresolved binding - its fixed up whenever its needed, see
        // UnresolvedReferenceBinding.resolve()
        if (this.environment.isProcessingAnnotations)
          throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the
        // type
        // if a type exists, check that its a valid type
        // it can be a NotFound problem type if its a secondary type referenced before its primary
        // type found in additional units
        // and it can be an unresolved type which is now being defined
        problemReporter().duplicateTypes(this.referenceContext, typeDecl);
        continue nextType;
      }
      if (this.fPackage != this.environment.defaultPackage
          && this.fPackage.getPackage(typeDecl.name) != null) {
        // if a package exists, it must be a valid package - cannot be a NotFound problem package
        // this is now a warning since a package does not really 'exist' until it contains a type,
        // see JLS v2, 7.4.3
        problemReporter().typeCollidesWithPackage(this.referenceContext, typeDecl);
      }

      if ((typeDecl.modifiers & ClassFileConstants.AccPublic) != 0) {
        char[] mainTypeName;
        if ((mainTypeName = this.referenceContext.getMainTypeName())
                != null // mainTypeName == null means that implementor of ICompilationUnit decided
            // to return null
            && !CharOperation.equals(mainTypeName, typeDecl.name)) {
          problemReporter().publicClassMustMatchFileName(this.referenceContext, typeDecl);
          // tolerate faulty main type name (91091), allow to proceed into type construction
        }
      }

      ClassScope child = new ClassScope(this, typeDecl);
      SourceTypeBinding type = child.buildType(null, this.fPackage, accessRestriction);
      if (firstIsSynthetic && i == 0) type.modifiers |= ClassFileConstants.AccSynthetic;
      if (type != null) this.topLevelTypes[count++] = type;
    }

    // shrink topLevelTypes... only happens if an error was reported
    if (count != this.topLevelTypes.length)
      System.arraycopy(
          this.topLevelTypes, 0, this.topLevelTypes = new SourceTypeBinding[count], 0, count);
  }