Skip to content

Commit cb87699

Browse files
brad4dcopybara-github
authored andcommitted
NamedType: resolve to NoResolvedType for typeof UnknownTypeName
Previously such types were resolved to `?`, which doesn't provide enough information for clutz to correctly generate `typeof` references for its .d.ts output file. PiperOrigin-RevId: 325449726
1 parent 5235e9e commit cb87699

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

src/com/google/javascript/rhino/jstype/NamedType.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,18 @@ private boolean resolveTypeof(ErrorReporter reporter) {
334334
String scopeName = reference.substring("typeof ".length());
335335
JSType type = resolutionScope.lookupQualifiedName(QualifiedName.of(scopeName));
336336
if (type == null || type.isUnknownType()) {
337-
warning(reporter, "Missing type for `typeof` value. The value must be declared and const.");
338-
setReferencedAndResolvedType(registry.getNativeType(JSTypeNative.UNKNOWN_TYPE), reporter);
337+
if (registry.isForwardDeclaredType(scopeName)) {
338+
// Preserve the "typeof" as a `NoResolvedType`.
339+
// This is depended on by Clutz so it can generate `typeof ImportedType` instead of `any`
340+
// when `ImportedType` is not defined in the files it can see.
341+
setReferencedType(new NoResolvedType(registry, getReferenceName(), getTemplateTypes()));
342+
if (validator != null) {
343+
validator.apply(getReferencedType());
344+
}
345+
} else {
346+
warning(reporter, "Missing type for `typeof` value. The value must be declared and const.");
347+
setReferencedAndResolvedType(registry.getNativeType(JSTypeNative.UNKNOWN_TYPE), reporter);
348+
}
339349
} else {
340350
if (type.isLiteralObject()) {
341351
// Create an extra layer of wrapping so that the "typeof" name is preserved for namespaces.

src/com/google/javascript/rhino/testing/BaseJSTypeTestCase.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,11 @@
6060

6161
/** A base class for tests on {@code JSType}s. */
6262
public abstract class BaseJSTypeTestCase {
63-
protected static final String FORWARD_DECLARED_TYPE_NAME = "forwardDeclared";
6463

6564
protected static final Joiner LINE_JOINER = Joiner.on('\n');
6665

6766
protected final TestErrorReporter errorReporter = new TestErrorReporter();
68-
protected final JSTypeRegistry registry;
67+
protected JSTypeRegistry registry;
6968

7069
protected JSType ALL_TYPE;
7170
protected ObjectType NO_OBJECT_TYPE;
@@ -121,11 +120,16 @@ public BaseJSTypeTestCase() {
121120
public BaseJSTypeTestCase(JSTypeRegistry registry) {
122121
this.registry =
123122
(registry == null)
124-
? new JSTypeRegistry(errorReporter, ImmutableSet.of(FORWARD_DECLARED_TYPE_NAME))
123+
? new JSTypeRegistry(errorReporter, ImmutableSet.of())
125124
: registry;
126125
initTypes();
127126
}
128127

128+
protected void resetRegistryWithForwardDeclaredName(String name) {
129+
this.registry = new JSTypeRegistry(errorReporter, ImmutableSet.of(name));
130+
initTypes();
131+
}
132+
129133
@After
130134
public void validateWarningsAndErrors() {
131135
errorReporter.verifyHasEncounteredAllWarningsAndErrors();

src/com/google/javascript/rhino/testing/TypeSubject.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ public void isNotUnknown() {
130130
check("isUnknownType()").that(actualNonNull().isUnknownType()).isFalse();
131131
}
132132

133+
public void isNoResolvedType(String referenceName) {
134+
check("isNoResolvedType()").that(actual.isNoResolvedType()).isTrue();
135+
getReferenceNameIsEqualTo(referenceName);
136+
}
137+
133138
public void isNotEmpty() {
134139
check("isEmptyType()").that(actualNonNull().isEmptyType()).isFalse();
135140
}

test/com/google/javascript/rhino/jstype/JSTypeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public class JSTypeTest extends BaseJSTypeTestCase {
103103
@Before
104104
@SuppressWarnings({"MustBeClosedChecker"})
105105
public void setUp() throws Exception {
106+
resetRegistryWithForwardDeclaredName("forwardDeclared");
106107
try (JSTypeResolver.Closer closer = this.registry.getResolver().openForDefinition()) {
107108
final ObjectType googObject = registry.createAnonymousObjectType(null);
108109
MapBasedScope scope = new MapBasedScope(ImmutableMap.of("goog", googObject));

test/com/google/javascript/rhino/jstype/NamedTypeTest.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
import org.junit.runner.RunWith;
5656
import org.junit.runners.JUnit4;
5757

58-
/** @author [email protected] (Nick Santos) */
5958
@RunWith(JUnit4.class)
6059
public class NamedTypeTest extends BaseJSTypeTestCase {
6160

@@ -116,9 +115,11 @@ public void testResolutionPropagatesNamedTypePropertiesToResolvedType() {
116115

117116
@Test
118117
public void testStateOfForwardDeclaredType_Unresolved() {
118+
resetRegistryWithForwardDeclaredName("forwardDeclared");
119+
119120
try (JSTypeResolver.Closer closer = this.registry.getResolver().openForDefinition()) {
120121
// Given
121-
NamedType type = namedTypeBuilder(FORWARD_DECLARED_TYPE_NAME).build();
122+
NamedType type = namedTypeBuilder("forwardDeclared").build();
122123

123124
// Then
124125
assertThat(type.isResolved()).isFalse();
@@ -130,8 +131,10 @@ public void testStateOfForwardDeclaredType_Unresolved() {
130131

131132
@Test
132133
public void testStateOfForwardDeclaredType_UnsuccesfullyResolved() {
134+
resetRegistryWithForwardDeclaredName("forwardDeclared");
135+
133136
// Given
134-
NamedType type = namedTypeBuilder(FORWARD_DECLARED_TYPE_NAME).build();
137+
NamedType type = namedTypeBuilder("forwardDeclared").build();
135138

136139
// Then
137140
assertThat(type.isUnsuccessfullyResolved()).isTrue();
@@ -358,6 +361,18 @@ public void testBuilderForTypeof_emitsUnrecognizedTypeError() {
358361
"Missing type for `typeof` value. The value must be declared and const.");
359362
}
360363

364+
@Test
365+
public void testBuilderForTypeof_yieldsNoResolvedTypeWithForwardDeclaredName() {
366+
resetRegistryWithForwardDeclaredName("Foo");
367+
368+
NamedType.Builder typeofFooBuilder = NamedType
369+
.builder(registry, "typeof Foo")
370+
.setScope(emptyScope())
371+
.setResolutionKind(ResolutionKind.TYPEOF);
372+
373+
assertType(typeofFooBuilder.build()).isNoResolvedType("typeof Foo");
374+
}
375+
361376
@Test
362377
public void testBuilderForTypeof_requiresReferenceToStartWithTypeof() {
363378
NamedType.Builder typeofFooBuilder = NamedType.builder(registry, "Foo")

0 commit comments

Comments
 (0)