Skip to content

Commit

Permalink
Prepare TypedScopeCreator to work with ES6 block scopes.
Browse files Browse the repository at this point in the history
1. Split the `scope` field in TypedScopeCreator.AbstractScopeBuilder into `currentScope` and `currentHoistScope`.  These currently point to the same object, so no behavior change is expected.
2. Declare qualified names on their owner's scope: this is a slight behavior change that improves type inference.  It's included in this change because with the introduction of block scopes, the question of which scope to declare a qualified name on is becoming more nuanced, so it helps to start by making the behavior more consistent.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=191386776
  • Loading branch information
shicks authored and lauraharker committed Apr 4, 2018
1 parent 8ae7242 commit 68a5bd7
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 144 deletions.
15 changes: 15 additions & 0 deletions src/com/google/javascript/jscomp/FunctionTypeBuilder.java
Expand Up @@ -90,6 +90,7 @@ final class FunctionTypeBuilder {
// TODO(johnlenz): verify we want both template and class template lists instead of a unified // TODO(johnlenz): verify we want both template and class template lists instead of a unified
// list. // list.
private ImmutableList<TemplateType> classTemplateTypeNames = ImmutableList.of(); private ImmutableList<TemplateType> classTemplateTypeNames = ImmutableList.of();
private TypedScope declarationScope = null;


static final DiagnosticType EXTENDS_WITHOUT_TYPEDEF = DiagnosticType.warning( static final DiagnosticType EXTENDS_WITHOUT_TYPEDEF = DiagnosticType.warning(
"JSC_EXTENDS_WITHOUT_TYPEDEF", "JSC_EXTENDS_WITHOUT_TYPEDEF",
Expand Down Expand Up @@ -246,6 +247,16 @@ FunctionTypeBuilder setContents(@Nullable FunctionContents contents) {
return this; return this;
} }


/**
* Sets a declaration scope explicitly. This is important with block scopes because a function
* declared in an inner scope with 'var' needs to use the inner scope to resolve names, but needs
* to be declared in the outer scope.
*/
FunctionTypeBuilder setDeclarationScope(TypedScope declarationScope) {
this.declarationScope = declarationScope;
return this;
}

/** /**
* Infer the parameter and return types of a function from * Infer the parameter and return types of a function from
* the parameter and return types of the function it is overriding. * the parameter and return types of the function it is overriding.
Expand Down Expand Up @@ -876,6 +887,10 @@ static boolean isFunctionTypeDeclaration(JSDocInfo info) {
* care of most scope-declaring. * care of most scope-declaring.
*/ */
private TypedScope getScopeDeclaredIn() { private TypedScope getScopeDeclaredIn() {
if (declarationScope != null) {
return declarationScope;
}

int dotIndex = fnName.indexOf('.'); int dotIndex = fnName.indexOf('.');
if (dotIndex != -1) { if (dotIndex != -1) {
String rootVarName = fnName.substring(0, dotIndex); String rootVarName = fnName.substring(0, dotIndex);
Expand Down
21 changes: 21 additions & 0 deletions src/com/google/javascript/jscomp/NodeUtil.java
Expand Up @@ -5133,6 +5133,27 @@ static String getBestLValueName(@Nullable Node lValue) {
return lValue.getQualifiedName(); return lValue.getQualifiedName();
} }


/** Gets the root of a qualified name l-value. */
static Node getBestLValueRoot(@Nullable Node lValue) {
if (lValue == null) {
return null;
}
switch (lValue.getToken()) {
case STRING_KEY:
// NOTE: beware of getBestLValue returning null (or be null-permissive?)
return getBestLValueRoot(NodeUtil.getBestLValue(lValue.getParent()));
case GETPROP:
case GETELEM:
return getBestLValueRoot(lValue.getFirstChild());
case THIS:
case SUPER:
case NAME:
return lValue;
default:
return null;
}
}

/** /**
* @return true iff the result of the expression is consumed. * @return true iff the result of the expression is consumed.
*/ */
Expand Down

0 comments on commit 68a5bd7

Please sign in to comment.