Skip to content

Commit

Permalink
Move Iterable type transformation function into its own class for r…
Browse files Browse the repository at this point in the history
…euse.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=228000581
  • Loading branch information
nreid260 authored and lauraharker committed Jan 7, 2019
1 parent 3df2370 commit 157b3b7
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/Es6RewriteGenerators.java
Expand Up @@ -266,7 +266,7 @@ private class SingleGeneratorFunctionTranspiler {
if (genFunc.getJSType() != null && genFunc.getJSType().isFunctionType()) { if (genFunc.getJSType() != null && genFunc.getJSType().isFunctionType()) {
FunctionType fnType = genFunc.getJSType().toMaybeFunctionType(); FunctionType fnType = genFunc.getJSType().toMaybeFunctionType();
this.originalGenReturnType = fnType.getReturnType(); this.originalGenReturnType = fnType.getReturnType();
yieldType = TypeCheck.getTemplateTypeOfGenerator(registry, originalGenReturnType); yieldType = JsIterables.getElementType(originalGenReturnType, registry);
} }


JSType globalContextType = registry.getGlobalType("$jscomp.generator.Context"); JSType globalContextType = registry.getGlobalType("$jscomp.generator.Context");
Expand Down
55 changes: 55 additions & 0 deletions src/com/google/javascript/jscomp/JsIterables.java
@@ -0,0 +1,55 @@
/*
* Copyright 2014 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.javascript.jscomp;

import static com.google.javascript.rhino.jstype.JSTypeNative.UNKNOWN_TYPE;

import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import com.google.javascript.rhino.jstype.TemplateTypeMap;

/**
* Models type transformations of JavaScript `Iterable` and `Iterator` types.
*
* <p>These tranformations can be especially helpful when working with generator functions.
* `Generator` is a subtype of `Iterable`.
*/
final class JsIterables {

/**
* Returns the given `Iterable`s element type.
*
* <p>If the given type is not an `Iterator` or `Iterable`, returns the unknown type.
*/
static final JSType getElementType(JSType iterableOrIterator, JSTypeRegistry typeRegistry) {
TemplateTypeMap templateTypeMap =
iterableOrIterator
// Remember that `string` will box to a `Iterable`.
.autobox()
.getTemplateTypeMap();

if (templateTypeMap.hasTemplateKey(typeRegistry.getIterableTemplate())) {
// `Iterable<SomeElementType>` or `Generator<SomeElementType>`
return templateTypeMap.getResolvedTemplateType(typeRegistry.getIterableTemplate());
} else if (templateTypeMap.hasTemplateKey(typeRegistry.getIteratorTemplate())) {
// `Iterator<SomeElementType>`
return templateTypeMap.getResolvedTemplateType(typeRegistry.getIteratorTemplate());
}
return typeRegistry.getNativeType(UNKNOWN_TYPE);
}

private JsIterables() {}
}
30 changes: 2 additions & 28 deletions src/com/google/javascript/jscomp/TypeCheck.java
Expand Up @@ -2552,7 +2552,7 @@ private void visitReturn(NodeTraversal t, Node n) {
} else if (enclosingFunction.isGeneratorFunction()) { } else if (enclosingFunction.isGeneratorFunction()) {
// Unwrap the template variable from a generator function's declared return type. // Unwrap the template variable from a generator function's declared return type.
// e.g. if returnType is "Generator<string>", make it just "string". // e.g. if returnType is "Generator<string>", make it just "string".
returnType = getTemplateTypeOfGenerator(returnType); returnType = JsIterables.getElementType(returnType, typeRegistry);
} else if (enclosingFunction.isAsyncFunction()) { } else if (enclosingFunction.isAsyncFunction()) {
// e.g. `!Promise<string>` => `string|!IThenable<string>` // e.g. `!Promise<string>` => `string|!IThenable<string>`
// We transform the expected return type rather than the actual return type so that the // We transform the expected return type rather than the actual return type so that the
Expand Down Expand Up @@ -2592,7 +2592,7 @@ private void visitYield(NodeTraversal t, Node n) {
if (jsType.isFunctionType()) { if (jsType.isFunctionType()) {
FunctionType functionType = jsType.toMaybeFunctionType(); FunctionType functionType = jsType.toMaybeFunctionType();
JSType returnType = functionType.getReturnType(); JSType returnType = functionType.getReturnType();
declaredYieldType = getTemplateTypeOfGenerator(returnType); declaredYieldType = JsIterables.getElementType(returnType, typeRegistry);
} }


// fetching the yielded value's type // fetching the yielded value's type
Expand Down Expand Up @@ -2624,32 +2624,6 @@ private void visitYield(NodeTraversal t, Node n) {
"Yielded type does not match declared return type."); "Yielded type does not match declared return type.");
} }


private JSType getTemplateTypeOfGenerator(JSType generator) {
return getTemplateTypeOfGenerator(typeRegistry, generator);
}

/**
* Returns the given type's resolved template type corresponding to the corresponding to the
* Generator, Iterable or Iterator template key if possible.
*
* <p>If the given type is not an Iterator or Iterable, returns the unknown type..
*/
static JSType getTemplateTypeOfGenerator(JSTypeRegistry typeRegistry, JSType generator) {
TemplateTypeMap templateTypeMap = generator.autobox().getTemplateTypeMap();
if (templateTypeMap.hasTemplateKey(typeRegistry.getIterableTemplate())) {
// Generator JSDoc says
// @return {!Iterable<SomeElementType>}
// or
// @return {!Generator<SomeElementType>}
return templateTypeMap.getResolvedTemplateType(typeRegistry.getIterableTemplate());
} else if (templateTypeMap.hasTemplateKey(typeRegistry.getIteratorTemplate())) {
// Generator JSDoc says
// @return {!Iterator<SomeElementType>}
return templateTypeMap.getResolvedTemplateType(typeRegistry.getIteratorTemplate());
}
return typeRegistry.getNativeType(UNKNOWN_TYPE);
}

private void visitTaggedTemplateLit(NodeTraversal t, Node n) { private void visitTaggedTemplateLit(NodeTraversal t, Node n) {
Node tag = n.getFirstChild(); Node tag = n.getFirstChild();
JSType tagType = tag.getJSType().restrictByNotNullOrUndefined(); JSType tagType = tag.getJSType().restrictByNotNullOrUndefined();
Expand Down

0 comments on commit 157b3b7

Please sign in to comment.