Merge pull request #30970 from Microsoft/incrementalLateSymbol

When adding resolvedMembers ensure lateBoundSymbol is added whether it was previously checked or not
This commit is contained in:
Sheetal Nandi
2019-04-17 16:04:12 -07:00
committed by GitHub
13 changed files with 387 additions and 4 deletions

View File

@@ -6714,11 +6714,12 @@ namespace ts {
const links = getSymbolLinks(symbol);
if (!links.lateSymbol && some(symbol.declarations, hasLateBindableName)) {
// force late binding of members/exports. This will set the late-bound symbol
const parent = getMergedSymbol(symbol.parent)!;
if (some(symbol.declarations, hasStaticModifier)) {
getExportsOfSymbol(symbol.parent!);
getExportsOfSymbol(parent);
}
else {
getMembersOfSymbol(symbol.parent!);
getMembersOfSymbol(parent);
}
}
return links.lateSymbol || (links.lateSymbol = symbol);

View File

@@ -92,6 +92,7 @@
"unittests/tsbuild/amdModulesWithOut.ts",
"unittests/tsbuild/emptyFiles.ts",
"unittests/tsbuild/graphOrdering.ts",
"unittests/tsbuild/lateBoundSymbol.ts",
"unittests/tsbuild/missingExtendedFile.ts",
"unittests/tsbuild/outFile.ts",
"unittests/tsbuild/referencesWithRootDirInParent.ts",

View File

@@ -285,8 +285,10 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
let newFs: vfs.FileSystem;
let actualReadFileMap: Map<number>;
let host: fakes.SolutionBuilderHost;
let beforeBuildTime: number;
let afterBuildTime: number;
before(() => {
assert.equal(fs.statSync(lastProjectOutputJs).mtimeMs, firstBuildTime, "First build timestamp is correct");
beforeBuildTime = fs.statSync(lastProjectOutputJs).mtimeMs;
tick();
newFs = fs.shadow();
tick();
@@ -298,13 +300,17 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
expectedBuildInfoFilesForSectionBaselines,
modifyFs: incrementalModifyFs,
}));
assert.equal(newFs.statSync(lastProjectOutputJs).mtimeMs, time(), "Second build timestamp is correct");
afterBuildTime = newFs.statSync(lastProjectOutputJs).mtimeMs;
});
after(() => {
newFs = undefined!;
actualReadFileMap = undefined!;
host = undefined!;
});
it("verify build output times", () => {
assert.equal(beforeBuildTime, firstBuildTime, "First build timestamp is correct");
assert.equal(afterBuildTime, time(), "Second build timestamp is correct");
});
if (!baselineOnly || verifyDiagnostics) {
it(`verify diagnostics`, () => {
host.assertDiagnosticMessages(...(incrementalExpectedDiagnostics || emptyArray));

View File

@@ -0,0 +1,47 @@
namespace ts {
describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => {
let projFs: vfs.FileSystem;
const { time, tick } = getTime();
before(() => {
projFs = loadProjectFromDisk("tests/projects/lateBoundSymbol", time);
});
after(() => {
projFs = undefined!; // Release the contents
});
verifyTsbuildOutput({
scenario: "interface is merged and contains late bound member",
projFs: () => projFs,
time,
tick,
proj: "lateBoundSymbol",
rootNames: ["/src/tsconfig.json"],
expectedMapFileNames: emptyArray,
lastProjectOutputJs: "/src/src/main.js",
outputFiles: [
"/src/src/hkt.js",
"/src/src/main.js",
"/src/tsconfig.tsbuildinfo",
],
initialBuild: {
modifyFs: noop,
expectedDiagnostics: [
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/src/hkt.js"],
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
]
},
incrementalDtsUnchangedBuild: {
modifyFs: fs => replaceText(fs, "/src/src/main.ts", "const x = 10;", ""),
expectedDiagnostics: [
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/src/hkt.js", "src/src/main.ts"],
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
]
},
baselineOnly: true,
verifyDiagnostics: true
});
});
}

View File

@@ -0,0 +1,113 @@
//// [/src/src/main.js]
"use strict";
exports.__esModule = true;
var sym = Symbol();
//// [/src/src/main.ts]
import { HKT } from "./hkt";
const sym = Symbol();
declare module "./hkt" {
interface HKT<T> {
[sym]: { a: T }
}
}
type A = HKT<number>[typeof sym];
//// [/src/tsconfig.tsbuildinfo]
{
"program": {
"fileInfos": {
"/lib/lib.es5.d.ts": {
"version": "/lib/lib.es5.d.ts",
"signature": "/lib/lib.es5.d.ts"
},
"/lib/lib.es2015.d.ts": {
"version": "/lib/lib.es2015.d.ts",
"signature": "/lib/lib.es2015.d.ts"
},
"/lib/lib.es2015.core.d.ts": {
"version": "/lib/lib.es2015.core.d.ts",
"signature": "/lib/lib.es2015.core.d.ts"
},
"/lib/lib.es2015.collection.d.ts": {
"version": "/lib/lib.es2015.collection.d.ts",
"signature": "/lib/lib.es2015.collection.d.ts"
},
"/lib/lib.es2015.generator.d.ts": {
"version": "/lib/lib.es2015.generator.d.ts",
"signature": "/lib/lib.es2015.generator.d.ts"
},
"/lib/lib.es2015.iterable.d.ts": {
"version": "/lib/lib.es2015.iterable.d.ts",
"signature": "/lib/lib.es2015.iterable.d.ts"
},
"/lib/lib.es2015.promise.d.ts": {
"version": "/lib/lib.es2015.promise.d.ts",
"signature": "/lib/lib.es2015.promise.d.ts"
},
"/lib/lib.es2015.proxy.d.ts": {
"version": "/lib/lib.es2015.proxy.d.ts",
"signature": "/lib/lib.es2015.proxy.d.ts"
},
"/lib/lib.es2015.reflect.d.ts": {
"version": "/lib/lib.es2015.reflect.d.ts",
"signature": "/lib/lib.es2015.reflect.d.ts"
},
"/lib/lib.es2015.symbol.d.ts": {
"version": "/lib/lib.es2015.symbol.d.ts",
"signature": "/lib/lib.es2015.symbol.d.ts"
},
"/lib/lib.es2015.symbol.wellknown.d.ts": {
"version": "/lib/lib.es2015.symbol.wellknown.d.ts",
"signature": "/lib/lib.es2015.symbol.wellknown.d.ts"
},
"/src/src/hkt.ts": {
"version": "675797797",
"signature": "2373810515"
},
"/src/src/main.ts": {
"version": "-27494779858",
"signature": "-7779857705"
}
},
"options": {
"rootDir": "/src/src",
"lib": [
"lib.es2015.d.ts"
],
"incremental": true,
"configFilePath": "/src/tsconfig.json"
},
"referencedMap": {
"/src/src/main.ts": [
"/src/src/hkt.ts"
]
},
"exportedModulesMap": {
"/src/src/main.ts": [
"/src/src/hkt.ts"
]
},
"semanticDiagnosticsPerFile": [
"/lib/lib.es2015.collection.d.ts",
"/lib/lib.es2015.core.d.ts",
"/lib/lib.es2015.d.ts",
"/lib/lib.es2015.generator.d.ts",
"/lib/lib.es2015.iterable.d.ts",
"/lib/lib.es2015.promise.d.ts",
"/lib/lib.es2015.proxy.d.ts",
"/lib/lib.es2015.reflect.d.ts",
"/lib/lib.es2015.symbol.d.ts",
"/lib/lib.es2015.symbol.wellknown.d.ts",
"/lib/lib.es5.d.ts",
"/src/src/hkt.ts",
"/src/src/main.ts"
]
},
"version": "FakeTSVersion"
}

View File

@@ -0,0 +1,106 @@
//// [/src/src/hkt.js]
"use strict";
exports.__esModule = true;
//// [/src/src/main.js]
"use strict";
exports.__esModule = true;
var sym = Symbol();
var x = 10;
//// [/src/tsconfig.tsbuildinfo]
{
"program": {
"fileInfos": {
"/lib/lib.es5.d.ts": {
"version": "/lib/lib.es5.d.ts",
"signature": "/lib/lib.es5.d.ts"
},
"/lib/lib.es2015.d.ts": {
"version": "/lib/lib.es2015.d.ts",
"signature": "/lib/lib.es2015.d.ts"
},
"/lib/lib.es2015.core.d.ts": {
"version": "/lib/lib.es2015.core.d.ts",
"signature": "/lib/lib.es2015.core.d.ts"
},
"/lib/lib.es2015.collection.d.ts": {
"version": "/lib/lib.es2015.collection.d.ts",
"signature": "/lib/lib.es2015.collection.d.ts"
},
"/lib/lib.es2015.generator.d.ts": {
"version": "/lib/lib.es2015.generator.d.ts",
"signature": "/lib/lib.es2015.generator.d.ts"
},
"/lib/lib.es2015.iterable.d.ts": {
"version": "/lib/lib.es2015.iterable.d.ts",
"signature": "/lib/lib.es2015.iterable.d.ts"
},
"/lib/lib.es2015.promise.d.ts": {
"version": "/lib/lib.es2015.promise.d.ts",
"signature": "/lib/lib.es2015.promise.d.ts"
},
"/lib/lib.es2015.proxy.d.ts": {
"version": "/lib/lib.es2015.proxy.d.ts",
"signature": "/lib/lib.es2015.proxy.d.ts"
},
"/lib/lib.es2015.reflect.d.ts": {
"version": "/lib/lib.es2015.reflect.d.ts",
"signature": "/lib/lib.es2015.reflect.d.ts"
},
"/lib/lib.es2015.symbol.d.ts": {
"version": "/lib/lib.es2015.symbol.d.ts",
"signature": "/lib/lib.es2015.symbol.d.ts"
},
"/lib/lib.es2015.symbol.wellknown.d.ts": {
"version": "/lib/lib.es2015.symbol.wellknown.d.ts",
"signature": "/lib/lib.es2015.symbol.wellknown.d.ts"
},
"/src/src/hkt.ts": {
"version": "675797797",
"signature": "2373810515"
},
"/src/src/main.ts": {
"version": "-28387946490",
"signature": "-7779857705"
}
},
"options": {
"rootDir": "/src/src",
"lib": [
"lib.es2015.d.ts"
],
"incremental": true,
"configFilePath": "/src/tsconfig.json"
},
"referencedMap": {
"/src/src/main.ts": [
"/src/src/hkt.ts"
]
},
"exportedModulesMap": {
"/src/src/main.ts": [
"/src/src/hkt.ts"
]
},
"semanticDiagnosticsPerFile": [
"/lib/lib.es2015.collection.d.ts",
"/lib/lib.es2015.core.d.ts",
"/lib/lib.es2015.d.ts",
"/lib/lib.es2015.generator.d.ts",
"/lib/lib.es2015.iterable.d.ts",
"/lib/lib.es2015.promise.d.ts",
"/lib/lib.es2015.proxy.d.ts",
"/lib/lib.es2015.reflect.d.ts",
"/lib/lib.es2015.symbol.d.ts",
"/lib/lib.es2015.symbol.wellknown.d.ts",
"/lib/lib.es5.d.ts",
"/src/src/hkt.ts",
"/src/src/main.ts"
]
},
"version": "FakeTSVersion"
}

View File

@@ -0,0 +1,18 @@
//// [uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts]
const FOO_SYMBOL = Symbol('Foo');
declare global {
interface Promise<T> {
[FOO_SYMBOL]?: number;
}
}
export function foo<T>(p: Promise<T>) {
p[FOO_SYMBOL] = 3;
}
//// [uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.js]
const FOO_SYMBOL = Symbol('Foo');
export function foo(p) {
p[FOO_SYMBOL] = 3;
}

View File

@@ -0,0 +1,29 @@
=== tests/cases/compiler/uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts ===
const FOO_SYMBOL = Symbol('Foo');
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
declare global {
>global : Symbol(global, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 33))
interface Promise<T> {
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 2, 16))
>T : Symbol(T, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 3, 22))
[FOO_SYMBOL]?: number;
>[FOO_SYMBOL] : Symbol(Promise[FOO_SYMBOL], Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 3, 26))
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
}
}
export function foo<T>(p: Promise<T>) {
>foo : Symbol(foo, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 6, 1))
>T : Symbol(T, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 20))
>p : Symbol(p, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 23))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 2, 16))
>T : Symbol(T, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 20))
p[FOO_SYMBOL] = 3;
>p : Symbol(p, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 23))
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
}

View File

@@ -0,0 +1,28 @@
=== tests/cases/compiler/uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts ===
const FOO_SYMBOL = Symbol('Foo');
>FOO_SYMBOL : unique symbol
>Symbol('Foo') : unique symbol
>Symbol : SymbolConstructor
>'Foo' : "Foo"
declare global {
>global : any
interface Promise<T> {
[FOO_SYMBOL]?: number;
>[FOO_SYMBOL] : number | undefined
>FOO_SYMBOL : unique symbol
}
}
export function foo<T>(p: Promise<T>) {
>foo : <T>(p: Promise<T>) => void
>p : Promise<T>
p[FOO_SYMBOL] = 3;
>p[FOO_SYMBOL] = 3 : 3
>p[FOO_SYMBOL] : number | undefined
>p : Promise<T>
>FOO_SYMBOL : unique symbol
>3 : 3
}

View File

@@ -0,0 +1,13 @@
// @strict: true
// @target: es6
const FOO_SYMBOL = Symbol('Foo');
declare global {
interface Promise<T> {
[FOO_SYMBOL]?: number;
}
}
export function foo<T>(p: Promise<T>) {
p[FOO_SYMBOL] = 3;
}

View File

@@ -0,0 +1 @@
export interface HKT<T> { }

View File

@@ -0,0 +1,11 @@
import { HKT } from "./hkt";
const sym = Symbol();
declare module "./hkt" {
interface HKT<T> {
[sym]: { a: T }
}
}
const x = 10;
type A = HKT<number>[typeof sym];

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"rootDir": "src",
"lib": [
"es2015"
],
"incremental": true
}
}