Search in sources :

Example 1 with MatchResult

use of com.google.javascript.jscomp.TypeMatchingStrategy.MatchResult in project closure-compiler by google.

the class TemplateAstMatcher method matchesNode.

/**
 * Returns whether two nodes are equivalent, taking into account the template parameters that were
 * provided to this matcher. If the template comparison node is a parameter node, then only the
 * types of the node must match. If the template node is a string literal, only match string
 * literals. Otherwise, the node must be equal and the child nodes must be equivalent according to
 * the same function. This differs from the built in Node equivalence function with the special
 * comparison.
 */
private boolean matchesNode(Node template, Node ast) {
    if (isTemplateParameterNode(template)) {
        int paramIndex = (int) (template.getDouble());
        Node previousMatch = paramNodeMatches.get(paramIndex);
        if (previousMatch != null) {
            // subsequent usages of the same named node are equivalent.
            return ast.isEquivalentTo(previousMatch);
        }
        // Only the types need to match for the template parameters, which allows
        // the template function to express arbitrary expressions.
        JSType templateType = template.getJSType();
        checkNotNull(templateType, "null template parameter type.");
        // we should treat them as "unknown" and perform loose matches.
        if (isUnresolvedType(templateType)) {
            return false;
        }
        MatchResult matchResult = typeMatchingStrategy.match(templateType, ast.getJSType());
        isLooseMatch = matchResult.isLooseMatch();
        boolean isMatch = matchResult.isMatch();
        if (isMatch && previousMatch == null) {
            paramNodeMatches.set(paramIndex, ast);
        }
        return isMatch;
    } else if (isTemplateLocalNameNode(template)) {
        // If this template name node was already matched against, then make sure
        // all subsequent usages of the same template name node are equivalent in
        // the matched code.
        // For example, this code will handle the case:
        // function template() {
        // var a = 'str';
        // fn(a);
        // }
        // 
        // will only match test code:
        // var b = 'str';
        // fn(b);
        // 
        // but it will not match:
        // var b = 'str';
        // fn('str');
        int paramIndex = (int) (template.getDouble());
        boolean previouslyMatched = this.localVarMatches.get(paramIndex) != null;
        if (previouslyMatched) {
            // subsequent usages of the same named node are equivalent.
            return ast.getString().equals(this.localVarMatches.get(paramIndex));
        } else {
            String originalName = ast.getOriginalName();
            String name = (originalName != null) ? originalName : ast.getString();
            this.localVarMatches.set(paramIndex, name);
        }
    } else if (isTemplateParameterStringLiteralNode(template)) {
        int paramIndex = (int) (template.getDouble());
        Node previousMatch = paramNodeMatches.get(paramIndex);
        if (previousMatch != null) {
            return ast.isEquivalentTo(previousMatch);
        }
        if (NodeUtil.isSomeCompileTimeConstStringValue(ast)) {
            paramNodeMatches.set(paramIndex, ast);
            return true;
        }
        return false;
    }
    // Template and AST shape has already been checked, but continue look for
    // other template variables (parameters and locals) that must be checked.
    Node templateChild = template.getFirstChild();
    Node astChild = ast.getFirstChild();
    while (templateChild != null) {
        if (!matchesNode(templateChild, astChild)) {
            return false;
        }
        templateChild = templateChild.getNext();
        astChild = astChild.getNext();
    }
    return true;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) MatchResult(com.google.javascript.jscomp.TypeMatchingStrategy.MatchResult)

Example 2 with MatchResult

use of com.google.javascript.jscomp.TypeMatchingStrategy.MatchResult in project closure-compiler by google.

the class TypeMatchingStrategyTest method assertMatch.

private static void assertMatch(TypeMatchingStrategy typeMatchingStrategy, String templateType, String type, boolean isMatch, boolean isLooseMatch) {
    // It's important that the test uses the same compiler to compile the template type and the
    // type to be matched. Otherwise, equal types won't be considered equal.
    Compiler compiler = new Compiler();
    compiler.disableThreads();
    CompilerOptions options = new CompilerOptions();
    options.setCheckTypes(true);
    options.setChecksOnly(true);
    compiler.compile(ImmutableList.of(SourceFile.fromCode("externs", EXTERNS)), ImmutableList.of(SourceFile.fromCode("test", String.format("/** @type {%s} */ var x; /** @type {%s} */ var y;", templateType, type))), options);
    Node script = compiler.getRoot().getLastChild().getFirstChild();
    Node xNode = script.getFirstChild();
    Node yNode = script.getLastChild();
    JSType templateJsType = xNode.getFirstChild().getJSType();
    JSType jsType = yNode.getFirstChild().getJSType();
    MatchResult matchResult = typeMatchingStrategy.match(templateJsType, jsType);
    assertWithMessage(isMatch ? "'" + templateJsType + "' should match '" + jsType + "'" : "'" + templateType + "' should not match '" + type + "'").that(matchResult.isMatch()).isEqualTo(isMatch);
    assertWithMessage(isLooseMatch ? "'" + templateType + "' should loosely match '" + type + "'" : "'" + templateType + "' should not loosely match '" + type + "'").that(matchResult.isLooseMatch()).isEqualTo(isLooseMatch);
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) MatchResult(com.google.javascript.jscomp.TypeMatchingStrategy.MatchResult)

Aggregations

MatchResult (com.google.javascript.jscomp.TypeMatchingStrategy.MatchResult)2 Node (com.google.javascript.rhino.Node)2 JSType (com.google.javascript.rhino.jstype.JSType)2