From 61ebcb49c7808030b78b01e0c85039a79290cf4b Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Fri, 17 Mar 2017 10:25:37 +0900 Subject: [PATCH 1/4] Allow exporting a binding before its declaration --- src/compiler/checker.ts | 7 +++++++ tests/baselines/reference/exportBinding.js | 19 +++++++++++++++++++ .../baselines/reference/exportBinding.symbols | 14 ++++++++++++++ tests/baselines/reference/exportBinding.types | 15 +++++++++++++++ .../conformance/es6/modules/exportBinding.ts | 5 +++++ 5 files changed, 60 insertions(+) create mode 100644 tests/baselines/reference/exportBinding.js create mode 100644 tests/baselines/reference/exportBinding.symbols create mode 100644 tests/baselines/reference/exportBinding.types create mode 100644 tests/cases/conformance/es6/modules/exportBinding.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 00498191f28..736b3154fbc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -742,6 +742,13 @@ namespace ts { // declaration is after usage, but it can still be legal if usage is deferred: // 1. inside a function // 2. inside an instance property initializer, a reference to a non-instance property + // 3. inside an export specifier + + if (usage.parent.kind === SyntaxKind.ExportSpecifier) { + // export specifiers do not use the variable, they only make it available for use + return true; + } + const container = getEnclosingBlockScopeContainer(declaration); const isInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(declaration) & ModifierFlags.Static); return isUsedInFunctionOrInstanceProperty(usage, isInstanceProperty, container); diff --git a/tests/baselines/reference/exportBinding.js b/tests/baselines/reference/exportBinding.js new file mode 100644 index 00000000000..5059c5356a3 --- /dev/null +++ b/tests/baselines/reference/exportBinding.js @@ -0,0 +1,19 @@ +//// [exportBinding.ts] +export { x } +const x = 'x' + +export { Y as Z } +class Y {} + + +//// [exportBinding.js] +"use strict"; +exports.__esModule = true; +var x = 'x'; +exports.x = x; +var Y = (function () { + function Y() { + } + return Y; +}()); +exports.Z = Y; diff --git a/tests/baselines/reference/exportBinding.symbols b/tests/baselines/reference/exportBinding.symbols new file mode 100644 index 00000000000..cb3b58a5776 --- /dev/null +++ b/tests/baselines/reference/exportBinding.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/es6/modules/exportBinding.ts === +export { x } +>x : Symbol(x, Decl(exportBinding.ts, 0, 8)) + +const x = 'x' +>x : Symbol(x, Decl(exportBinding.ts, 1, 5)) + +export { Y as Z } +>Y : Symbol(Z, Decl(exportBinding.ts, 3, 8)) +>Z : Symbol(Z, Decl(exportBinding.ts, 3, 8)) + +class Y {} +>Y : Symbol(Y, Decl(exportBinding.ts, 3, 17)) + diff --git a/tests/baselines/reference/exportBinding.types b/tests/baselines/reference/exportBinding.types new file mode 100644 index 00000000000..e2553ba1eaa --- /dev/null +++ b/tests/baselines/reference/exportBinding.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/es6/modules/exportBinding.ts === +export { x } +>x : "x" + +const x = 'x' +>x : "x" +>'x' : "x" + +export { Y as Z } +>Y : typeof Y +>Z : typeof Y + +class Y {} +>Y : Y + diff --git a/tests/cases/conformance/es6/modules/exportBinding.ts b/tests/cases/conformance/es6/modules/exportBinding.ts new file mode 100644 index 00000000000..1e6b0314f0b --- /dev/null +++ b/tests/cases/conformance/es6/modules/exportBinding.ts @@ -0,0 +1,5 @@ +export { x } +const x = 'x' + +export { Y as Z } +class Y {} From 8ec593aec2504a2257069032e14c1f9d7454b12c Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 6 Apr 2017 08:01:15 -0700 Subject: [PATCH 2/4] Support @types module resolution from scoped packages --- src/compiler/diagnosticMessages.json | 4 +++ src/compiler/moduleNameResolver.ts | 15 +++++++++- .../library-reference-scoped-packages.js | 11 +++++++ .../library-reference-scoped-packages.symbols | 7 +++++ ...brary-reference-scoped-packages.trace.json | 12 ++++++++ .../library-reference-scoped-packages.types | 8 +++++ tests/baselines/reference/scopedPackages.js | 20 +++++++++++++ .../reference/scopedPackages.symbols | 22 ++++++++++++++ .../reference/scopedPackages.trace.json | 30 +++++++++++++++++++ .../baselines/reference/scopedPackages.types | 22 ++++++++++++++ .../reference/scopedPackagesClassic.js | 12 ++++++++ .../reference/scopedPackagesClassic.symbols | 8 +++++ .../scopedPackagesClassic.trace.json | 9 ++++++ .../reference/scopedPackagesClassic.types | 9 ++++++ .../moduleResolution/scopedPackages.ts | 17 +++++++++++ .../moduleResolution/scopedPackagesClassic.ts | 10 +++++++ .../library-reference-scoped-packages.ts | 9 ++++++ 17 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/library-reference-scoped-packages.js create mode 100644 tests/baselines/reference/library-reference-scoped-packages.symbols create mode 100644 tests/baselines/reference/library-reference-scoped-packages.trace.json create mode 100644 tests/baselines/reference/library-reference-scoped-packages.types create mode 100644 tests/baselines/reference/scopedPackages.js create mode 100644 tests/baselines/reference/scopedPackages.symbols create mode 100644 tests/baselines/reference/scopedPackages.trace.json create mode 100644 tests/baselines/reference/scopedPackages.types create mode 100644 tests/baselines/reference/scopedPackagesClassic.js create mode 100644 tests/baselines/reference/scopedPackagesClassic.symbols create mode 100644 tests/baselines/reference/scopedPackagesClassic.trace.json create mode 100644 tests/baselines/reference/scopedPackagesClassic.types create mode 100644 tests/cases/conformance/moduleResolution/scopedPackages.ts create mode 100644 tests/cases/conformance/moduleResolution/scopedPackagesClassic.ts create mode 100644 tests/cases/conformance/references/library-reference-scoped-packages.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 075d4247460..6a5b6fa7526 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3177,6 +3177,10 @@ "category": "Message", "code": 6181 }, + "Scoped package detected, looking in '{0}'": { + "category": "Message", + "code": "6182" + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 5280c794725..44779c3b482 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -954,10 +954,23 @@ namespace ts { } nodeModulesAtTypesExists = false; } - return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, moduleName, nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); + return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state.host), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); } } + /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ + function mangleScopedPackage(moduleName: string, host: ModuleResolutionHost): string { + if (startsWith(moduleName, "@")) { + const replaceSlash = moduleName.replace(ts.directorySeparator, "__"); + if (replaceSlash !== moduleName) { + const mangled = replaceSlash.slice(1); // Take off the "@" + trace(host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); + return mangled; + } + } + return moduleName; + } + function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefined, moduleName: string, containingDirectory: string, traceEnabled: boolean, host: ModuleResolutionHost): SearchResult { const result = cache && cache.get(containingDirectory); if (result) { diff --git a/tests/baselines/reference/library-reference-scoped-packages.js b/tests/baselines/reference/library-reference-scoped-packages.js new file mode 100644 index 00000000000..3019008c16b --- /dev/null +++ b/tests/baselines/reference/library-reference-scoped-packages.js @@ -0,0 +1,11 @@ +//// [tests/cases/conformance/references/library-reference-scoped-packages.ts] //// + +//// [index.d.ts] +export const y = 0; + +//// [a.ts] +/// + + +//// [a.js] +/// diff --git a/tests/baselines/reference/library-reference-scoped-packages.symbols b/tests/baselines/reference/library-reference-scoped-packages.symbols new file mode 100644 index 00000000000..60ccaab89d2 --- /dev/null +++ b/tests/baselines/reference/library-reference-scoped-packages.symbols @@ -0,0 +1,7 @@ +=== /a.ts === +/// +No type information for this code. +No type information for this code.=== /node_modules/@types/beep__boop/index.d.ts === +export const y = 0; +>y : Symbol(y, Decl(index.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/library-reference-scoped-packages.trace.json b/tests/baselines/reference/library-reference-scoped-packages.trace.json new file mode 100644 index 00000000000..54dcf95fe50 --- /dev/null +++ b/tests/baselines/reference/library-reference-scoped-packages.trace.json @@ -0,0 +1,12 @@ +[ + "======== Resolving type reference directive '@beep/boop', containing file '/a.ts', root directory 'types'. ========", + "Resolving with primary search path 'types'.", + "Directory 'types/@beep' does not exist, skipping all lookups in it.", + "Looking up in 'node_modules' folder, initial location '/'.", + "Scoped package detected, looking in 'beep__boop'", + "File '/node_modules/@types/beep__boop.d.ts' does not exist.", + "File '/node_modules/@types/beep__boop/package.json' does not exist.", + "File '/node_modules/@types/beep__boop/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/@types/beep__boop/index.d.ts', result '/node_modules/@types/beep__boop/index.d.ts'.", + "======== Type reference directive '@beep/boop' was successfully resolved to '/node_modules/@types/beep__boop/index.d.ts', primary: false. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/library-reference-scoped-packages.types b/tests/baselines/reference/library-reference-scoped-packages.types new file mode 100644 index 00000000000..bbb3062d98b --- /dev/null +++ b/tests/baselines/reference/library-reference-scoped-packages.types @@ -0,0 +1,8 @@ +=== /a.ts === +/// +No type information for this code. +No type information for this code.=== /node_modules/@types/beep__boop/index.d.ts === +export const y = 0; +>y : 0 +>0 : 0 + diff --git a/tests/baselines/reference/scopedPackages.js b/tests/baselines/reference/scopedPackages.js new file mode 100644 index 00000000000..75606d2e1b9 --- /dev/null +++ b/tests/baselines/reference/scopedPackages.js @@ -0,0 +1,20 @@ +//// [tests/cases/conformance/moduleResolution/scopedPackages.ts] //// + +//// [index.d.ts] +export const x: number; + +//// [index.d.ts] +export const y: number; + +//// [z.d.ts] +export const z: number; + +//// [a.ts] +import { x } from "@cow/boy"; +import { y } from "@be/bop"; +import { z } from "@be/bop/e/z"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/scopedPackages.symbols b/tests/baselines/reference/scopedPackages.symbols new file mode 100644 index 00000000000..e992c4d9375 --- /dev/null +++ b/tests/baselines/reference/scopedPackages.symbols @@ -0,0 +1,22 @@ +=== /a.ts === +import { x } from "@cow/boy"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +import { y } from "@be/bop"; +>y : Symbol(y, Decl(a.ts, 1, 8)) + +import { z } from "@be/bop/e/z"; +>z : Symbol(z, Decl(a.ts, 2, 8)) + +=== /node_modules/@cow/boy/index.d.ts === +export const x: number; +>x : Symbol(x, Decl(index.d.ts, 0, 12)) + +=== /node_modules/@types/be__bop/index.d.ts === +export const y: number; +>y : Symbol(y, Decl(index.d.ts, 0, 12)) + +=== /node_modules/@types/be__bop/e/z.d.ts === +export const z: number; +>z : Symbol(z, Decl(z.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/scopedPackages.trace.json b/tests/baselines/reference/scopedPackages.trace.json new file mode 100644 index 00000000000..20df3bec172 --- /dev/null +++ b/tests/baselines/reference/scopedPackages.trace.json @@ -0,0 +1,30 @@ +[ + "======== Resolving module '@cow/boy' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module '@cow/boy' from 'node_modules' folder, target file type 'TypeScript'.", + "File '/node_modules/@cow/boy.ts' does not exist.", + "File '/node_modules/@cow/boy.tsx' does not exist.", + "File '/node_modules/@cow/boy.d.ts' does not exist.", + "File '/node_modules/@cow/boy/package.json' does not exist.", + "File '/node_modules/@cow/boy/index.ts' does not exist.", + "File '/node_modules/@cow/boy/index.tsx' does not exist.", + "File '/node_modules/@cow/boy/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/@cow/boy/index.d.ts', result '/node_modules/@cow/boy/index.d.ts'.", + "======== Module name '@cow/boy' was successfully resolved to '/node_modules/@cow/boy/index.d.ts'. ========", + "======== Resolving module '@be/bop' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module '@be/bop' from 'node_modules' folder, target file type 'TypeScript'.", + "Scoped package detected, looking in 'be__bop'", + "File '/node_modules/@types/be__bop.d.ts' does not exist.", + "File '/node_modules/@types/be__bop/package.json' does not exist.", + "File '/node_modules/@types/be__bop/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/@types/be__bop/index.d.ts', result '/node_modules/@types/be__bop/index.d.ts'.", + "======== Module name '@be/bop' was successfully resolved to '/node_modules/@types/be__bop/index.d.ts'. ========", + "======== Resolving module '@be/bop/e/z' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module '@be/bop/e/z' from 'node_modules' folder, target file type 'TypeScript'.", + "Scoped package detected, looking in 'be__bop/e/z'", + "File '/node_modules/@types/be__bop/e/z.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/@types/be__bop/e/z.d.ts', result '/node_modules/@types/be__bop/e/z.d.ts'.", + "======== Module name '@be/bop/e/z' was successfully resolved to '/node_modules/@types/be__bop/e/z.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/scopedPackages.types b/tests/baselines/reference/scopedPackages.types new file mode 100644 index 00000000000..c876590f54a --- /dev/null +++ b/tests/baselines/reference/scopedPackages.types @@ -0,0 +1,22 @@ +=== /a.ts === +import { x } from "@cow/boy"; +>x : number + +import { y } from "@be/bop"; +>y : number + +import { z } from "@be/bop/e/z"; +>z : number + +=== /node_modules/@cow/boy/index.d.ts === +export const x: number; +>x : number + +=== /node_modules/@types/be__bop/index.d.ts === +export const y: number; +>y : number + +=== /node_modules/@types/be__bop/e/z.d.ts === +export const z: number; +>z : number + diff --git a/tests/baselines/reference/scopedPackagesClassic.js b/tests/baselines/reference/scopedPackagesClassic.js new file mode 100644 index 00000000000..f42acde2306 --- /dev/null +++ b/tests/baselines/reference/scopedPackagesClassic.js @@ -0,0 +1,12 @@ +//// [tests/cases/conformance/moduleResolution/scopedPackagesClassic.ts] //// + +//// [index.d.ts] +export const x = 0; + +//// [a.ts] +import { x } from "@see/saw"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/scopedPackagesClassic.symbols b/tests/baselines/reference/scopedPackagesClassic.symbols new file mode 100644 index 00000000000..e0d84f44c91 --- /dev/null +++ b/tests/baselines/reference/scopedPackagesClassic.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "@see/saw"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +=== /node_modules/@types/see__saw/index.d.ts === +export const x = 0; +>x : Symbol(x, Decl(index.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/scopedPackagesClassic.trace.json b/tests/baselines/reference/scopedPackagesClassic.trace.json new file mode 100644 index 00000000000..c58c7d2ed10 --- /dev/null +++ b/tests/baselines/reference/scopedPackagesClassic.trace.json @@ -0,0 +1,9 @@ +[ + "======== Resolving module '@see/saw' from '/a.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "Scoped package detected, looking in 'see__saw'", + "File '/node_modules/@types/see__saw.d.ts' does not exist.", + "File '/node_modules/@types/see__saw/package.json' does not exist.", + "File '/node_modules/@types/see__saw/index.d.ts' exist - use it as a name resolution result.", + "======== Module name '@see/saw' was successfully resolved to '/node_modules/@types/see__saw/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/scopedPackagesClassic.types b/tests/baselines/reference/scopedPackagesClassic.types new file mode 100644 index 00000000000..65047f2436d --- /dev/null +++ b/tests/baselines/reference/scopedPackagesClassic.types @@ -0,0 +1,9 @@ +=== /a.ts === +import { x } from "@see/saw"; +>x : 0 + +=== /node_modules/@types/see__saw/index.d.ts === +export const x = 0; +>x : 0 +>0 : 0 + diff --git a/tests/cases/conformance/moduleResolution/scopedPackages.ts b/tests/cases/conformance/moduleResolution/scopedPackages.ts new file mode 100644 index 00000000000..b604f10d7ec --- /dev/null +++ b/tests/cases/conformance/moduleResolution/scopedPackages.ts @@ -0,0 +1,17 @@ +// @noImplicitReferences: true +// @traceResolution: true +// @typeRoots: types + +// @filename: /node_modules/@cow/boy/index.d.ts +export const x: number; + +// @filename: /node_modules/@types/be__bop/index.d.ts +export const y: number; + +// @filename: /node_modules/@types/be__bop/e/z.d.ts +export const z: number; + +// @filename: /a.ts +import { x } from "@cow/boy"; +import { y } from "@be/bop"; +import { z } from "@be/bop/e/z"; diff --git a/tests/cases/conformance/moduleResolution/scopedPackagesClassic.ts b/tests/cases/conformance/moduleResolution/scopedPackagesClassic.ts new file mode 100644 index 00000000000..41b6fc09e19 --- /dev/null +++ b/tests/cases/conformance/moduleResolution/scopedPackagesClassic.ts @@ -0,0 +1,10 @@ +// @noImplicitReferences: true +// @traceResolution: true +// @typeRoots: types +// @moduleResolution: classic + +// @filename: /node_modules/@types/see__saw/index.d.ts +export const x = 0; + +// @filename: /a.ts +import { x } from "@see/saw"; diff --git a/tests/cases/conformance/references/library-reference-scoped-packages.ts b/tests/cases/conformance/references/library-reference-scoped-packages.ts new file mode 100644 index 00000000000..86a1ad3e93d --- /dev/null +++ b/tests/cases/conformance/references/library-reference-scoped-packages.ts @@ -0,0 +1,9 @@ +// @noImplicitReferences: true +// @traceResolution: true +// @typeRoots: types + +// @filename: /node_modules/@types/beep__boop/index.d.ts +export const y = 0; + +// @filename: /a.ts +/// From e9f95e2296e66b6fd2afc51663309426bbf3e0ae Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 10 Apr 2017 09:06:26 -0700 Subject: [PATCH 3/4] Only trace if traceEnabled --- src/compiler/moduleNameResolver.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 44779c3b482..e42088c3a2b 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -954,17 +954,19 @@ namespace ts { } nodeModulesAtTypesExists = false; } - return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state.host), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); + return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); } } /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ - function mangleScopedPackage(moduleName: string, host: ModuleResolutionHost): string { + function mangleScopedPackage(moduleName: string, state: ModuleResolutionState): string { if (startsWith(moduleName, "@")) { const replaceSlash = moduleName.replace(ts.directorySeparator, "__"); if (replaceSlash !== moduleName) { const mangled = replaceSlash.slice(1); // Take off the "@" - trace(host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); + } return mangled; } } From 6fd86538473619837dff923de37faaee360d6742 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 17 Apr 2017 14:04:05 -0700 Subject: [PATCH 4/4] Fix globalPlugins TSServer Flag **Bug** globalPlugins flag not being threaded through IOSession object properly **Fix** Pass these flags to superclass in IOSession --- src/server/server.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/server.ts b/src/server/server.ts index 433c7e16ab1..5ba1fce30d9 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -401,7 +401,9 @@ namespace ts.server { byteLength: Buffer.byteLength, hrtime: process.hrtime, logger, - canUseEvents}); + canUseEvents, + globalPlugins: options.globalPlugins, + pluginProbeLocations: options.pluginProbeLocations}); if (telemetryEnabled && typingsInstaller) { typingsInstaller.setTelemetrySender(this);