Resolve Json file when module resolution strategy is node

This commit is contained in:
Sheetal Nandi
2018-02-23 13:54:39 -08:00
parent 4d284d617f
commit 5771adbbe7
22 changed files with 252 additions and 10 deletions
+1 -1
View File
@@ -2084,7 +2084,7 @@ namespace ts {
}
// May be an untyped module. If so, ignore resolutionDiagnostic.
if (resolvedModule && !extensionIsTypeScript(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
if (resolvedModule && !resolutionExtensionIsTypeScriptOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
if (isForAugmentation) {
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
+5 -1
View File
@@ -2758,7 +2758,7 @@ namespace ts {
}
}
const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx];
const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx, Extension.Json];
export function removeFileExtension(path: string): string {
for (const ext of extensionsToRemove) {
const extensionless = tryRemoveExtension(path, ext);
@@ -3091,6 +3091,10 @@ namespace ts {
return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts;
}
export function resolutionExtensionIsTypeScriptOrJson(ext: Extension) {
return extensionIsTypeScript(ext) || ext === Extension.Json;
}
/**
* Gets the extension from a path.
* Path must have a valid extension.
+9 -4
View File
@@ -48,6 +48,7 @@ namespace ts {
enum Extensions {
TypeScript, /** '.ts', '.tsx', or '.d.ts' */
JavaScript, /** '.js' or '.jsx' */
Json, /** '.json' */
DtsOnly /** Only '.d.ts' */
}
@@ -730,7 +731,7 @@ namespace ts {
const failedLookupLocations: string[] = [];
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
const result = jsOnly ? tryResolve(Extensions.JavaScript) : (tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript));
const result = (jsOnly ? tryResolve(Extensions.JavaScript) : (tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript))) || tryResolve(Extensions.Json);
if (result && result.value) {
const { resolved, originalPath, isExternalLibraryImport } = result.value;
return createResolvedModuleWithFailedLookupLocations(resolved, originalPath, isExternalLibraryImport, failedLookupLocations);
@@ -889,7 +890,7 @@ namespace ts {
// If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
// e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
if (hasJavaScriptFileExtension(candidate)) {
if (hasJavaScriptFileExtension(candidate) || fileExtensionIs(candidate, Extension.Json)) {
const extensionless = removeFileExtension(candidate);
if (state.traceEnabled) {
const extension = candidate.substring(extensionless.length);
@@ -916,6 +917,8 @@ namespace ts {
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts);
case Extensions.JavaScript:
return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
case Extensions.Json:
return tryExtension(Extension.Json);
}
function tryExtension(ext: Extension): PathAndExtension | undefined {
@@ -1013,7 +1016,7 @@ namespace ts {
}
function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): PathAndExtension | undefined {
const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, jsonContent, candidate, state);
const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript && extensions !== Extensions.Json, jsonContent, candidate, state);
if (!file) {
return undefined;
}
@@ -1052,6 +1055,8 @@ namespace ts {
switch (extensions) {
case Extensions.JavaScript:
return extension === Extension.Js || extension === Extension.Jsx;
case Extensions.Json:
return extension === Extension.Json;
case Extensions.TypeScript:
return extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Dts;
case Extensions.DtsOnly:
@@ -1127,7 +1132,7 @@ namespace ts {
if (packageResult) {
return packageResult;
}
if (extensions !== Extensions.JavaScript) {
if (extensions !== Extensions.JavaScript && extensions !== Extensions.Json) {
const nodeModulesAtTypes = combinePaths(nodeModulesFolder, "@types");
let nodeModulesAtTypesExists = nodeModulesFolderExists;
if (nodeModulesFolderExists && !directoryProbablyExists(nodeModulesAtTypes, state.host)) {
+14 -2
View File
@@ -260,6 +260,7 @@ namespace ts {
return visitNodes(cbNode, cbNodes, (<Block>node).statements);
case SyntaxKind.SourceFile:
return visitNodes(cbNode, cbNodes, (<SourceFile>node).statements) ||
visitNode(cbNode, (<JsonSourceFile>node).jsonObject) ||
visitNode(cbNode, (<SourceFile>node).endOfFileToken);
case SyntaxKind.VariableStatement:
return visitNodes(cbNode, cbNodes, node.decorators) ||
@@ -660,6 +661,13 @@ namespace ts {
export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
scriptKind = ensureScriptKind(fileName, scriptKind);
if (scriptKind === ScriptKind.JSON) {
const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes);
result.statements = <any>emptyArray;
result.typeReferenceDirectives = emptyArray;
result.amdDependencies = emptyArray;
return result;
}
initializeState(sourceText, languageVersion, syntaxCursor, scriptKind);
@@ -681,8 +689,8 @@ namespace ts {
return isInvalid ? entityName : undefined;
}
export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON);
export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): JsonSourceFile {
initializeState(sourceText, languageVersion, syntaxCursor, ScriptKind.JSON);
// Set source file so that errors will be reported with this file name
sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false);
const result = <JsonSourceFile>sourceFile;
@@ -701,6 +709,10 @@ namespace ts {
parseExpected(SyntaxKind.OpenBraceToken);
}
if (setParentNodes) {
fixupParentReferences(sourceFile);
}
sourceFile.parseDiagnostics = parseDiagnostics;
clearState();
return result;
Executable → Regular
+2 -1
View File
@@ -1975,7 +1975,7 @@ namespace ts {
}
const isFromNodeModulesSearch = resolution.isExternalLibraryImport;
const isJsFile = !extensionIsTypeScript(resolution.extension);
const isJsFile = !resolutionExtensionIsTypeScriptOrJson(resolution.extension);
const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile;
const resolvedFileName = resolution.resolvedFileName;
@@ -2404,6 +2404,7 @@ namespace ts {
switch (extension) {
case Extension.Ts:
case Extension.Dts:
case Extension.Json:
// These are always allowed.
return undefined;
case Extension.Tsx:
+1 -1
View File
@@ -1207,7 +1207,7 @@ namespace Harness {
}
const programFileNames = programFiles.map(file => file.unitName);
const programFileNames = programFiles.map(file => file.unitName).filter(fileName => !ts.fileExtensionIs(fileName, ts.Extension.Json));
const compilerHost = createCompilerHost(
programFiles.concat(otherFiles),
@@ -471,6 +471,10 @@ namespace ts {
"File 'node_modules/a.jsx' does not exist.",
"File 'node_modules/a/index.js' does not exist.",
"File 'node_modules/a/index.jsx' does not exist.",
"Loading module 'a' from 'node_modules' folder, target file type 'Json'.",
"File 'node_modules/a/package.json' does not exist.",
"File 'node_modules/a.json' does not exist.",
"File 'node_modules/a/index.json' does not exist.",
"======== Module name 'a' was not resolved. ========"
],
"initialProgram: execute module resolution normally.");
@@ -3221,6 +3221,10 @@ namespace ts.projectSystem {
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"Loading module 'lib' from 'node_modules' folder, target file type 'Json'.",
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"======== Module name 'lib' was not resolved. ========",
`Auto discovery for typings is enabled in project '${proj.getProjectName()}'. Running extra resolution pass for module 'lib' using cache location '/a/cache'.`,
"File '/a/cache/node_modules/lib.d.ts' does not exist.",
@@ -15,6 +15,13 @@
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"Loading module 'foo' from 'node_modules' folder, target file type 'Json'.",
"Directory '/a/b/c/d/e/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/b/c/d/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/b/c/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"======== Module name 'foo' was not resolved. ========",
"======== Resolving module 'foo' from '/a/b/c/lib.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
@@ -11,6 +11,11 @@
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"Loading module 'foo' from 'node_modules' folder, target file type 'Json'.",
"Directory '/a/b/c/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/b/node_modules' does not exist, skipping all lookups in it.",
"Directory '/a/node_modules' does not exist, skipping all lookups in it.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"======== Module name 'foo' was not resolved. ========",
"======== Resolving module 'foo' from '/a/b/c/d/e/app.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
@@ -5,5 +5,7 @@
"Directory '/foo/' does not exist, skipping all lookups in it.",
"Loading module as file / folder, candidate module location '/foo/', target file type 'JavaScript'.",
"Directory '/foo/' does not exist, skipping all lookups in it.",
"Loading module as file / folder, candidate module location '/foo/', target file type 'Json'.",
"Directory '/foo/' does not exist, skipping all lookups in it.",
"======== Module name './foo/' was not resolved. ========"
]
@@ -31,5 +31,18 @@
"Directory '/node_modules/normalize.css/normalize.css' does not exist, skipping all lookups in it.",
"File '/node_modules/normalize.css/index.js' does not exist.",
"File '/node_modules/normalize.css/index.jsx' does not exist.",
"Loading module 'normalize.css' from 'node_modules' folder, target file type 'Json'.",
"'package.json' does not have a 'typings' field.",
"'package.json' does not have a 'types' field.",
"'package.json' has 'main' field 'normalize.css' that references '/node_modules/normalize.css/normalize.css'.",
"Found 'package.json' at '/node_modules/normalize.css/package.json'.",
"File '/node_modules/normalize.css.json' does not exist.",
"'package.json' has 'main' field 'normalize.css' that references '/node_modules/normalize.css/normalize.css'.",
"File '/node_modules/normalize.css/normalize.css' exist - use it as a name resolution result.",
"File '/node_modules/normalize.css/normalize.css' has an unsupported extension, so skipping it.",
"Loading module as file / folder, candidate module location '/node_modules/normalize.css/normalize.css', target file type 'Json'.",
"File '/node_modules/normalize.css/normalize.css.json' does not exist.",
"Directory '/node_modules/normalize.css/normalize.css' does not exist, skipping all lookups in it.",
"File '/node_modules/normalize.css/index.json' does not exist.",
"======== Module name 'normalize.css' was not resolved. ========"
]
@@ -34,5 +34,12 @@
"'package.json' does not have a 'main' field.",
"File '/node_modules/foo/index.js' does not exist.",
"File '/node_modules/foo/index.jsx' does not exist.",
"Loading module 'foo' from 'node_modules' folder, target file type 'Json'.",
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'foo.js' that references '/node_modules/foo/foo.js'.",
"Found 'package.json' at '/node_modules/foo/package.json'.",
"File '/node_modules/foo.json' does not exist.",
"'package.json' does not have a 'main' field.",
"File '/node_modules/foo/index.json' does not exist.",
"======== Module name 'foo' was not resolved. ========"
]
@@ -31,5 +31,17 @@
"File '/node_modules/foo/oof/index.jsx' does not exist.",
"File '/node_modules/foo/index.js' does not exist.",
"File '/node_modules/foo/index.jsx' does not exist.",
"Loading module 'foo' from 'node_modules' folder, target file type 'Json'.",
"'package.json' does not have a 'typings' field.",
"'package.json' does not have a 'types' field.",
"'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.",
"Found 'package.json' at '/node_modules/foo/package.json'.",
"File '/node_modules/foo.json' does not exist.",
"'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.",
"File '/node_modules/foo/oof' does not exist.",
"Loading module as file / folder, candidate module location '/node_modules/foo/oof', target file type 'Json'.",
"File '/node_modules/foo/oof.json' does not exist.",
"File '/node_modules/foo/oof/index.json' does not exist.",
"File '/node_modules/foo/index.json' does not exist.",
"======== Module name 'foo' was not resolved. ========"
]
@@ -17,5 +17,13 @@
"Loading module as file / folder, candidate module location '/foo/foo.ts', target file type 'JavaScript'.",
"Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"'baseUrl' option is set to '/', using this value to resolve non-relative module name 'foo'.",
"'paths' option is specified, looking for a pattern to match module name 'foo'.",
"Module name 'foo', matched pattern 'foo'.",
"Trying substitution 'foo/foo.ts', candidate module location: 'foo/foo.ts'.",
"File '/foo/foo.ts' does not exist.",
"Loading module as file / folder, candidate module location '/foo/foo.ts', target file type 'Json'.",
"Loading module 'foo' from 'node_modules' folder, target file type 'Json'.",
"Directory '/node_modules' does not exist, skipping all lookups in it.",
"======== Module name 'foo' was not resolved. ========"
]
@@ -0,0 +1,22 @@
tests/cases/compiler/file1.ts(1,21): error TS2306: File 'tests/cases/compiler/b.json' is not a module.
tests/cases/compiler/file1.ts(3,21): error TS2306: File 'tests/cases/compiler/b.json' is not a module.
==== tests/cases/compiler/file1.ts (2 errors) ====
import b1 = require('./b');
~~~~~
!!! error TS2306: File 'tests/cases/compiler/b.json' is not a module.
let x = b1.a;
import b2 = require('./b.json');
~~~~~~~~~~
!!! error TS2306: File 'tests/cases/compiler/b.json' is not a module.
if (x) {
let b = b2.b;
x = (b1.b === b);
}
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,28 @@
//// [tests/cases/compiler/requireOfJsonFile.ts] ////
//// [file1.ts]
import b1 = require('./b');
let x = b1.a;
import b2 = require('./b.json');
if (x) {
let b = b2.b;
x = (b1.b === b);
}
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [b.js]
//// [file1.js]
"use strict";
exports.__esModule = true;
var b1 = require("./b");
var x = b1.a;
var b2 = require("./b.json");
if (x) {
var b = b2.b;
x = (b1.b === b);
}
@@ -0,0 +1,32 @@
=== tests/cases/compiler/file1.ts ===
import b1 = require('./b');
>b1 : Symbol(b1, Decl(file1.ts, 0, 0))
let x = b1.a;
>x : Symbol(x, Decl(file1.ts, 1, 3))
>b1 : Symbol(b1, Decl(file1.ts, 0, 0))
import b2 = require('./b.json');
>b2 : Symbol(b2, Decl(file1.ts, 1, 13))
if (x) {
>x : Symbol(x, Decl(file1.ts, 1, 3))
let b = b2.b;
>b : Symbol(b, Decl(file1.ts, 4, 7))
>b2 : Symbol(b2, Decl(file1.ts, 1, 13))
x = (b1.b === b);
>x : Symbol(x, Decl(file1.ts, 1, 3))
>b1 : Symbol(b1, Decl(file1.ts, 0, 0))
>b : Symbol(b, Decl(file1.ts, 4, 7))
}
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,45 @@
=== tests/cases/compiler/file1.ts ===
import b1 = require('./b');
>b1 : any
let x = b1.a;
>x : any
>b1.a : any
>b1 : any
>a : any
import b2 = require('./b.json');
>b2 : any
if (x) {
>x : any
let b = b2.b;
>b : any
>b2.b : any
>b2 : any
>b : any
x = (b1.b === b);
>x = (b1.b === b) : boolean
>x : any
>(b1.b === b) : boolean
>b1.b === b : boolean
>b1.b : any
>b1 : any
>b : any
>b : any
}
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { [x: string]: any; "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -17,6 +17,10 @@
"File '/foo/node_modules/xyz.jsx' does not exist.",
"File '/node_modules/xyz.js' does not exist.",
"File '/node_modules/xyz.jsx' does not exist.",
"Loading module 'xyz' from 'node_modules' folder, target file type 'Json'.",
"Directory '/foo/bar/node_modules' does not exist, skipping all lookups in it.",
"File '/foo/node_modules/xyz.json' does not exist.",
"File '/node_modules/xyz.json' does not exist.",
"======== Module name 'xyz' was not resolved. ========",
"======== Resolving module 'pdq' from '/foo/bar/a.ts'. ========",
"Module resolution kind is not specified, using 'NodeJs'.",
@@ -36,6 +40,10 @@
"File '/foo/node_modules/pdq.jsx' does not exist.",
"File '/node_modules/pdq.js' does not exist.",
"File '/node_modules/pdq.jsx' does not exist.",
"Loading module 'pdq' from 'node_modules' folder, target file type 'Json'.",
"Directory '/foo/bar/node_modules' does not exist, skipping all lookups in it.",
"File '/foo/node_modules/pdq.json' does not exist.",
"File '/node_modules/pdq.json' does not exist.",
"======== Module name 'pdq' was not resolved. ========",
"======== Resolving module 'abc' from '/foo/bar/a.ts'. ========",
"Module resolution kind is not specified, using 'NodeJs'.",
@@ -55,6 +63,10 @@
"File '/foo/node_modules/abc.jsx' does not exist.",
"File '/node_modules/abc.js' does not exist.",
"File '/node_modules/abc.jsx' does not exist.",
"Loading module 'abc' from 'node_modules' folder, target file type 'Json'.",
"Directory '/foo/bar/node_modules' does not exist, skipping all lookups in it.",
"File '/foo/node_modules/abc.json' does not exist.",
"File '/node_modules/abc.json' does not exist.",
"======== Module name 'abc' was not resolved. ========",
"======== Resolving type reference directive 'grumpy', containing file '/foo/bar/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========",
"Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'.",
@@ -11,6 +11,9 @@
"Directory '/src/node_modules' does not exist, skipping all lookups in it.",
"File '/node_modules/xyz.js' does not exist.",
"File '/node_modules/xyz.jsx' does not exist.",
"Loading module 'xyz' from 'node_modules' folder, target file type 'Json'.",
"Directory '/src/node_modules' does not exist, skipping all lookups in it.",
"File '/node_modules/xyz.json' does not exist.",
"======== Module name 'xyz' was not resolved. ========",
"======== Resolving type reference directive 'foo', containing file '/src/__inferred type names__.ts', root directory '/node_modules/@types'. ========",
"Resolving with primary search path '/node_modules/@types'.",
+16
View File
@@ -0,0 +1,16 @@
// @module: commonjs
// @Filename: file1.ts
import b1 = require('./b');
let x = b1.a;
import b2 = require('./b.json');
if (x) {
let b = b2.b;
x = (b1.b === b);
}
// @Filename: b.json
{
"a": true,
"b": "hello"
}