Package com.google.dart.engine.internal.resolver

Source Code of com.google.dart.engine.internal.resolver.IncrementalResolver

/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.internal.resolver;

import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.ClassDeclaration;
import com.google.dart.engine.ast.ClassTypeAlias;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.ast.ConstructorDeclaration;
import com.google.dart.engine.ast.Declaration;
import com.google.dart.engine.ast.FunctionDeclaration;
import com.google.dart.engine.ast.FunctionTypeAlias;
import com.google.dart.engine.ast.MethodDeclaration;
import com.google.dart.engine.context.AnalysisException;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.error.AnalysisErrorListener;
import com.google.dart.engine.internal.scope.Scope;
import com.google.dart.engine.internal.scope.ScopeBuilder;
import com.google.dart.engine.source.Source;

/**
* Instances of the class {@code IncrementalResolver} resolve the smallest portion of an AST
* structure that we currently know how to resolve.
*/
public class IncrementalResolver {
  /**
   * The element for the library containing the compilation unit being visited.
   */
  private LibraryElement definingLibrary;

  /**
   * The source representing the compilation unit being visited.
   */
  private Source source;

  /**
   * The object used to access the types from the core library.
   */
  private TypeProvider typeProvider;

  /**
   * The error listener that will be informed of any errors that are found during resolution.
   */
  private AnalysisErrorListener errorListener;

  /**
   * Initialize a newly created incremental resolver to resolve a node in the given source in the
   * given library, reporting errors to the given error listener.
   *
   * @param definingLibrary the element for the library containing the compilation unit being
   *          visited
   * @param source the source representing the compilation unit being visited
   * @param typeProvider the object used to access the types from the core library
   * @param errorListener the error listener that will be informed of any errors that are found
   *          during resolution
   */
  public IncrementalResolver(LibraryElement definingLibrary, Source source,
      TypeProvider typeProvider, AnalysisErrorListener errorListener) {
    this.definingLibrary = definingLibrary;
    this.source = source;
    this.typeProvider = typeProvider;
    this.errorListener = errorListener;
  }

  /**
   * Resolve the given node, reporting any errors or warnings to the given listener.
   *
   * @param node the root of the AST structure to be resolved
   * @throws AnalysisException if the node could not be resolved
   */
  public void resolve(AstNode node) throws AnalysisException {
    AstNode rootNode = findResolutionRoot(node);
    Scope scope = ScopeBuilder.scopeFor(rootNode, errorListener);
    if (elementModelChanged(rootNode.getParent())) {
      throw new AnalysisException("Cannot resolve node: element model changed");
    }
    resolveTypes(node, scope);
    resolveVariables(node, scope);
    resolveReferences(node, scope);
  }

  /**
   * Return {@code true} if the given node can be resolved independently of any other nodes.
   * <p>
   * <b>Note:</b> This method needs to be kept in sync with {@link ScopeBuilder#scopeForAstNode}.
   *
   * @param node the node being tested
   * @return {@code true} if the given node can be resolved independently of any other nodes
   */
  private boolean canBeResolved(AstNode node) {
    return node instanceof ClassDeclaration || node instanceof ClassTypeAlias
        || node instanceof CompilationUnit || node instanceof ConstructorDeclaration
        || node instanceof FunctionDeclaration || node instanceof FunctionTypeAlias
        || node instanceof MethodDeclaration;
  }

  /**
   * Return {@code true} if the portion of the element model defined by the given node has changed.
   *
   * @param node the node defining the portion of the element model being tested
   * @return {@code true} if the element model defined by the given node has changed
   * @throws AnalysisException if the correctness of the element model cannot be determined
   */
  private boolean elementModelChanged(AstNode node) throws AnalysisException {
    Element element = getElement(node);
    if (element == null) {
      throw new AnalysisException("Cannot resolve node: a " + node.getClass().getSimpleName()
          + " does not define an element");
    }
    DeclarationMatcher matcher = new DeclarationMatcher();
    return !matcher.matches(node, element);
  }

  /**
   * Starting at the given node, find the smallest AST node that can be resolved independently of
   * any other nodes. Return the node that was found.
   *
   * @param node the node at which the search is to begin
   * @return the smallest AST node that can be resolved independently of any other nodes
   * @throws AnalysisException if there is no such node
   */
  private AstNode findResolutionRoot(AstNode node) throws AnalysisException {
    AstNode result = node;
    AstNode parent = result.getParent();
    while (parent != null && !canBeResolved(parent)) {
      result = parent;
      parent = result.getParent();
    }
    if (parent == null) {
      throw new AnalysisException("Cannot resolve node: no resolvable node");
    }
    return result;
  }

  /**
   * Return the element defined by the given node, or {@code null} if the node does not define an
   * element.
   *
   * @param node the node defining the element to be returned
   * @return the element defined by the given node
   */
  private Element getElement(AstNode node) {
    if (node instanceof Declaration) {
      return ((Declaration) node).getElement();
    } else if (node instanceof CompilationUnit) {
      return ((CompilationUnit) node).getElement();
    }
    return null;
  }

  private void resolveReferences(AstNode node, Scope scope) {
    ResolverVisitor visitor = new ResolverVisitor(
        definingLibrary,
        source,
        typeProvider,
        scope,
        errorListener);
    node.accept(visitor);
  }

  private void resolveTypes(AstNode node, Scope scope) {
    TypeResolverVisitor visitor = new TypeResolverVisitor(
        definingLibrary,
        source,
        typeProvider,
        scope,
        errorListener);
    node.accept(visitor);
  }

  private void resolveVariables(AstNode node, Scope scope) {
    VariableResolverVisitor visitor = new VariableResolverVisitor(
        definingLibrary,
        source,
        typeProvider,
        scope,
        errorListener);
    node.accept(visitor);
  }
}
TOP

Related Classes of com.google.dart.engine.internal.resolver.IncrementalResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.