Clean up api so that parsing returns JsonSourceFile

This commit is contained in:
Sheetal Nandi
2016-11-23 16:15:34 -08:00
parent 6419de9b51
commit 0dd944aa14
15 changed files with 117 additions and 115 deletions
+37 -39
View File
@@ -462,7 +462,7 @@ namespace ts {
];
/* @internal */
export let typeAcquisitionDeclarations: CommandLineOption[] = [
export const typeAcquisitionDeclarations: CommandLineOption[] = [
{
/* @deprecated typingOptions.enableAutoDiscovery
* Use typeAcquisition.enable instead.
@@ -723,10 +723,10 @@ namespace ts {
* @param jsonText The text of the config file
*/
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
const { node, errors } = parseJsonText(fileName, jsonText);
const jsonSourceFile = parseJsonText(fileName, jsonText);
return {
config: convertToJson(node, errors),
error: errors.length ? errors[0] : undefined
config: convertToJson(jsonSourceFile, jsonSourceFile.parseDiagnostics),
error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
};
}
@@ -734,13 +734,13 @@ namespace ts {
* Read tsconfig.json file
* @param fileName The path to the config file
*/
export function readConfigFileToJsonNode(fileName: string, readFile: (path: string) => string): ParsedNodeResults<JsonNode> {
export function readConfigFileToJsonSourceFile(fileName: string, readFile: (path: string) => string): JsonSourceFile {
let text = "";
try {
text = readFile(fileName);
}
catch (e) {
return { errors: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] };
return <JsonSourceFile>{ parseDiagnostics: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] };
}
return parseJsonText(fileName, text);
}
@@ -819,8 +819,8 @@ namespace ts {
* @param jsonNode
* @param errors
*/
export function convertToJson(jsonNode: JsonNode, errors: Diagnostic[]): any {
return convertToJsonWorker(jsonNode, errors);
export function convertToJson(sourceFile: JsonSourceFile, errors: Diagnostic[]): any {
return convertToJsonWorker(sourceFile, errors);
}
/**
@@ -828,17 +828,15 @@ namespace ts {
* @param jsonNode
* @param errors
*/
function convertToJsonWorker(jsonNode: JsonNode, errors: Diagnostic[], knownRootOptions?: Map<CommandLineOption>, optionsIterator?: JsonConversionNotifier): any {
if (!jsonNode) {
function convertToJsonWorker(sourceFile: JsonSourceFile, errors: Diagnostic[], knownRootOptions?: Map<CommandLineOption>, optionsIterator?: JsonConversionNotifier): any {
if (!sourceFile.jsonObject) {
if (sourceFile.endOfFileToken) {
return {};
}
return undefined;
}
if (jsonNode.kind === SyntaxKind.EndOfFileToken) {
return {};
}
const sourceFile = <SourceFile>jsonNode.parent;
return convertObjectLiteralExpressionToJson(jsonNode, knownRootOptions);
return convertObjectLiteralExpressionToJson(sourceFile.jsonObject, knownRootOptions);
function convertObjectLiteralExpressionToJson(node: ObjectLiteralExpression, options?: Map<CommandLineOption>, extraKeyDiagnosticMessage?: DiagnosticMessage, optionsObject?: string): any {
const result: any = {};
@@ -1076,7 +1074,7 @@ namespace ts {
* file to. e.g. outDir
*/
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]): ParsedCommandLine {
return parseJsonConfigFileContentWorker(json, /*jsonNode*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack);
return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack);
}
/**
@@ -1086,8 +1084,8 @@ namespace ts {
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
*/
export function parseJsonNodeConfigFileContent(jsonNode: JsonNode, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]): ParsedCommandLine {
return parseJsonConfigFileContentWorker(/*json*/ undefined, jsonNode, host, basePath, existingOptions, configFileName, resolutionStack);
export function parseJsonSourceFileConfigFileContent(sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]): ParsedCommandLine {
return parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack);
}
/**
@@ -1097,8 +1095,8 @@ namespace ts {
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
*/
function parseJsonConfigFileContentWorker(json: any, jsonNode: JsonNode, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = []): ParsedCommandLine {
Debug.assert((json === undefined && jsonNode !== undefined) || (json !== undefined && jsonNode === undefined));
function parseJsonConfigFileContentWorker(json: any, sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = []): ParsedCommandLine {
Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
const errors: Diagnostic[] = [];
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName);
@@ -1107,7 +1105,7 @@ namespace ts {
options: {},
fileNames: [],
typeAcquisition: {},
raw: json || convertToJson(jsonNode, errors),
raw: json || convertToJson(sourceFile, errors),
errors: errors.concat(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))),
wildcardDirectories: {}
};
@@ -1141,7 +1139,7 @@ namespace ts {
switch (key) {
case "extends":
const extendsDiagnostic = getExtendsConfigPath(<string>value, (message, arg0) =>
createDiagnosticForNodeInSourceFile(<SourceFile>jsonNode.parent, node, message, arg0));
createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0));
if ((<Diagnostic>extendsDiagnostic).messageText) {
errors.push(<Diagnostic>extendsDiagnostic);
hasExtendsError = true;
@@ -1151,11 +1149,11 @@ namespace ts {
}
return;
case "excludes":
errors.push(createDiagnosticForNodeInSourceFile(<SourceFile>jsonNode.parent, propertyName, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, propertyName, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
return;
case "files":
if ((<string[]>value).length === 0) {
errors.push(createDiagnosticForNodeInSourceFile(<SourceFile>jsonNode.parent, node, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, node, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
}
return;
case "compileOnSave":
@@ -1164,7 +1162,7 @@ namespace ts {
}
}
};
json = convertToJsonWorker(jsonNode, errors, getTsconfigRootOptionsMap(), optionsIterator);
json = convertToJsonWorker(sourceFile, errors, getTsconfigRootOptionsMap(), optionsIterator);
if (!typeAcquisition) {
if (typingOptionstypeAcquisition) {
typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ?
@@ -1244,16 +1242,16 @@ namespace ts {
extendedConfigPath = `${extendedConfigPath}.json` as Path;
}
const extendedResult = readConfigFileToJsonNode(extendedConfigPath, path => host.readFile(path));
if (extendedResult.errors.length) {
errors.push(...extendedResult.errors);
const extendedResult = readConfigFileToJsonSourceFile(extendedConfigPath, path => host.readFile(path));
if (extendedResult.parseDiagnostics.length) {
errors.push(...extendedResult.parseDiagnostics);
return;
}
const extendedDirname = getDirectoryPath(extendedConfigPath);
const relativeDifference = convertToRelativePath(extendedDirname, basePath, getCanonicalFileName);
const updatePath: (path: string) => string = path => isRootedDiskPath(path) ? path : combinePaths(relativeDifference, path);
// Merge configs (copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios)
const result = parseJsonNodeConfigFileContent(extendedResult.node, host, extendedDirname, /*existingOptions*/undefined, getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath]));
const result = parseJsonSourceFileConfigFileContent(extendedResult, host, extendedDirname, /*existingOptions*/undefined, getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath]));
errors.push(...result.errors);
const [include, exclude, files] = map(["include", "exclude", "files"], key => {
if (!json[key] && result.raw[key]) {
@@ -1313,7 +1311,7 @@ namespace ts {
includeSpecs = ["**/*"];
}
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, jsonNode);
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, sourceFile);
if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
errors.push(
@@ -1328,7 +1326,7 @@ namespace ts {
}
function createCompilerDiagnosticForJson(message: DiagnosticMessage, arg0?: string, arg1?: string) {
if (!jsonNode) {
if (!sourceFile) {
errors.push(createCompilerDiagnostic(message, arg0, arg1));
}
}
@@ -1548,7 +1546,7 @@ namespace ts {
* @param host The host used to resolve files and directories.
* @param errors An array for diagnostic reporting.
*/
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], jsonNode: JsonNode): ExpandResult {
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], jsonSourceFile: JsonSourceFile): ExpandResult {
basePath = normalizePath(basePath);
// The exclude spec list is converted into a regular expression, which allows us to quickly
@@ -1567,11 +1565,11 @@ namespace ts {
const wildcardFileMap = createMap<string>();
if (include) {
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false, jsonNode, "include");
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false, jsonSourceFile, "include");
}
if (exclude) {
exclude = validateSpecs(exclude, errors, /*allowTrailingRecursion*/ true, jsonNode, "exclude");
exclude = validateSpecs(exclude, errors, /*allowTrailingRecursion*/ true, jsonSourceFile, "exclude");
}
// Wildcard directories (provided as part of a wildcard path) are stored in a
@@ -1627,7 +1625,7 @@ namespace ts {
};
}
function validateSpecs(specs: string[], errors: Diagnostic[], allowTrailingRecursion: boolean, jsonNode: JsonNode, specKey: string) {
function validateSpecs(specs: string[], errors: Diagnostic[], allowTrailingRecursion: boolean, jsonSourceFile: JsonSourceFile, specKey: string) {
const validSpecs: string[] = [];
for (const spec of specs) {
if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
@@ -1647,13 +1645,13 @@ namespace ts {
return validSpecs;
function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
if (jsonNode && jsonNode.kind === SyntaxKind.ObjectLiteralExpression) {
for (const property of jsonNode.properties) {
if (jsonSourceFile && jsonSourceFile.jsonObject) {
for (const property of jsonSourceFile.jsonObject.properties) {
if (property.kind === SyntaxKind.PropertyAssignment && getTextOfPropertyName(property.name) === specKey) {
const specsNode = <ArrayLiteralExpression>property.initializer;
for (const element of specsNode.elements) {
if (element.kind === SyntaxKind.StringLiteral && (<StringLiteral>element).text === spec) {
return createDiagnosticForNodeInSourceFile(<SourceFile>jsonNode.parent, element, message, spec);
return createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec);
}
}
}
+2
View File
@@ -1928,6 +1928,8 @@ namespace ts {
return ScriptKind.TS;
case ".tsx":
return ScriptKind.TSX;
case ".json":
return ScriptKind.JSON;
default:
return ScriptKind.Unknown;
}
+13 -17
View File
@@ -450,14 +450,12 @@ namespace ts {
return Parser.parseIsolatedEntityName(text, languageVersion);
}
export type ParsedNodeResults<T extends Node> = { node?: T; errors: Diagnostic[] };
/**
* Parse json text into SyntaxTree and return node and parse errors if any
* @param fileName
* @param sourceText
*/
export function parseJsonText(fileName: string, sourceText: string): ParsedNodeResults<JsonNode> {
export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
return Parser.parseJsonText(fileName, sourceText);
}
@@ -622,36 +620,34 @@ namespace ts {
return isInvalid ? entityName : undefined;
}
export function parseJsonText(fileName: string, sourceText: string): ParsedNodeResults<JsonNode> {
initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JS);
export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
initializeState(sourceText, ScriptTarget.ES2015, /*syntaxCursor*/ undefined, ScriptKind.JSON);
// Set source file so that errors will be reported with this file name
sourceFile = <SourceFile>{ kind: SyntaxKind.SourceFile, text: sourceText, fileName };
let node: JsonNode;
sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON);
const result = <JsonSourceFile>sourceFile;
// Prime the scanner.
nextToken();
if (token() === SyntaxKind.EndOfFileToken) {
node = <EndOfFileToken>parseTokenNode();
sourceFile.endOfFileToken = <EndOfFileToken>parseTokenNode();
}
else if (token() === SyntaxKind.OpenBraceToken ||
lookAhead(() => token() === SyntaxKind.StringLiteral)) {
node = parseObjectLiteralExpression();
parseExpected(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token);
result.jsonObject = parseObjectLiteralExpression();
sourceFile.endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, /*reportAtCurrentPosition*/ false, Diagnostics.Unexpected_token);
}
else {
parseExpected(SyntaxKind.OpenBraceToken);
}
if (node) {
node.parent = sourceFile;
}
const errors = parseDiagnostics;
sourceFile.parseDiagnostics = parseDiagnostics;
clearState();
return { node, errors };
return result;
}
function getLanguageVariant(scriptKind: ScriptKind) {
// .tsx and .jsx files are treated as jsx language variant.
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS ? LanguageVariant.JSX : LanguageVariant.Standard;
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
}
function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
@@ -669,7 +665,7 @@ namespace ts {
identifierCount = 0;
nodeCount = 0;
contextFlags = scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX ? NodeFlags.JavaScriptFile : NodeFlags.None;
contextFlags = scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JSON ? NodeFlags.JavaScriptFile : NodeFlags.None;
parseErrorBeforeNextFinishedNode = false;
// Initialize and prime the scanner before parsing the source elements.
+3 -3
View File
@@ -307,13 +307,13 @@ namespace ts {
}
const result = parseJsonText(configFileName, cachedConfigFileText);
reportDiagnostics(result.errors, /* compilerHost */ undefined);
if (!result.node) {
reportDiagnostics(result.parseDiagnostics, /* compilerHost */ undefined);
if (!result.endOfFileToken) {
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
const cwd = sys.getCurrentDirectory();
const configParseResult = parseJsonNodeConfigFileContent(result.node, sys, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), commandLine.options, getNormalizedAbsolutePath(configFileName, cwd));
const configParseResult = parseJsonSourceFileConfigFileContent(result, sys, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), commandLine.options, getNormalizedAbsolutePath(configFileName, cwd));
if (configParseResult.errors.length > 0) {
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
+6 -3
View File
@@ -527,8 +527,6 @@ namespace ts {
export type AtToken = Token<SyntaxKind.AtToken>;
export type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
export type JsonNode = ObjectLiteralExpression | EndOfFileToken;
export type Modifier
= Token<SyntaxKind.AbstractKeyword>
| Token<SyntaxKind.AsyncKeyword>
@@ -2189,6 +2187,10 @@ namespace ts {
/* @internal */ ambientModuleNames: string[];
}
export interface JsonSourceFile extends SourceFile {
jsonObject?: ObjectLiteralExpression;
}
export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
getSourceFile(fileName: string): SourceFile;
@@ -3261,7 +3263,8 @@ namespace ts {
JS = 1,
JSX = 2,
TS = 3,
TSX = 4
TSX = 4,
JSON = 5
}
export const enum ScriptTarget {
+2 -2
View File
@@ -1877,12 +1877,12 @@ namespace Harness {
const data = testUnitData[i];
if (ts.getBaseFileName(data.name).toLowerCase() === "tsconfig.json") {
const configJson = ts.parseJsonText(data.name, data.content);
assert.isTrue(configJson.node !== undefined);
assert.isTrue(configJson.endOfFileToken !== undefined);
let baseDir = ts.normalizePath(ts.getDirectoryPath(data.name));
if (rootDir) {
baseDir = ts.getNormalizedAbsolutePath(baseDir, rootDir);
}
tsConfig = ts.parseJsonNodeConfigFileContent(configJson.node, parseConfigHost, baseDir);
tsConfig = ts.parseJsonSourceFileConfigFileContent(configJson, parseConfigHost, baseDir);
tsConfig.options.configFilePath = data.name;
// delete entry from the list
+4 -11
View File
@@ -210,30 +210,23 @@ class ProjectRunner extends RunnerBase {
let errors: ts.Diagnostic[];
if (configFileName) {
const result = ts.readConfigFileToJsonNode(configFileName, getSourceFileText);
if (!result.node) {
return {
moduleKind,
errors: result.errors
};
}
const result = ts.readConfigFileToJsonSourceFile(configFileName, getSourceFileText);
const configParseHost: ts.ParseConfigHost = {
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
fileExists,
readDirectory,
readFile
};
const configParseResult = ts.parseJsonNodeConfigFileContent(result.node, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
const configParseResult = ts.parseJsonSourceFileConfigFileContent(result, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
if (configParseResult.errors.length > 0) {
return {
moduleKind,
errors: result.errors.concat(configParseResult.errors)
errors: result.parseDiagnostics.concat(configParseResult.errors)
};
}
inputFiles = configParseResult.fileNames;
compilerOptions = configParseResult.options;
errors = result.errors;
errors = result.parseDiagnostics;
}
const projectCompilerResult = compileProjectFiles(moduleKind, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
+1 -1
View File
@@ -81,7 +81,7 @@ namespace RWC {
readDirectory: Harness.IO.readDirectory,
readFile: Harness.IO.readFile
};
const configParseResult = ts.parseJsonNodeConfigFileContent(parsedTsconfigFileContents.node, configParseHost, ts.getDirectoryPath(tsconfigFile.path));
const configParseResult = ts.parseJsonSourceFileConfigFileContent(parsedTsconfigFileContents, configParseHost, ts.getDirectoryPath(tsconfigFile.path));
fileNames = configParseResult.fileNames;
opts.options = ts.extend(opts.options, configParseResult.options);
}
+18 -14
View File
@@ -110,21 +110,29 @@ namespace ts {
["under a case insensitive host", caseInsensitiveBasePath, caseInsensitiveHost],
["under a case sensitive host", caseSensitiveBasePath, caseSensitiveHost]
], ([testName, basePath, host]) => {
function getParseCommandLine(entry: string) {
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
return ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
}
function getParseCommandLineJsonSourceFile(entry: string) {
const jsonSourceFile = ts.readConfigFileToJsonSourceFile(entry, name => host.readFile(name));
assert(jsonSourceFile.endOfFileToken && !jsonSourceFile.parseDiagnostics.length, flattenDiagnosticMessageText(jsonSourceFile.parseDiagnostics[0] && jsonSourceFile.parseDiagnostics[0].messageText, "\n"));
return ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry);
}
function testSuccess(name: string, entry: string, expected: CompilerOptions, expectedFiles: string[]) {
it(name, () => {
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
const parsed = ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
const parsed = getParseCommandLine(entry);
assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n"));
expected.configFilePath = entry;
assert.deepEqual(parsed.options, expected);
assert.deepEqual(parsed.fileNames, expectedFiles);
});
it(name, () => {
const {node, errors} = ts.readConfigFileToJsonNode(entry, name => host.readFile(name));
assert(node && !errors.length, flattenDiagnosticMessageText(errors[0] && errors[0].messageText, "\n"));
const parsed = ts.parseJsonNodeConfigFileContent(node, host, basePath, {}, entry);
it(name + "with jsonSourceFile", () => {
const parsed = getParseCommandLineJsonSourceFile(entry);
assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n"));
expected.configFilePath = entry;
assert.deepEqual(parsed.options, expected);
@@ -134,16 +142,12 @@ namespace ts {
function testFailure(name: string, entry: string, expectedDiagnostics: { code: number, category: DiagnosticCategory, messageText: string }[]) {
it(name, () => {
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
const parsed = ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
const parsed = getParseCommandLine(entry);
verifyDiagnostics(parsed.errors, expectedDiagnostics);
});
it(name, () => {
const {node, errors} = ts.readConfigFileToJsonNode(entry, name => host.readFile(name));
assert(node && !errors.length, flattenDiagnosticMessageText(errors[0] && errors[0].messageText, "\n"));
const parsed = ts.parseJsonNodeConfigFileContent(node, host, basePath, {}, entry);
it(name + "with jsonSourceFile", () => {
const parsed = getParseCommandLineJsonSourceFile(entry);
verifyDiagnostics(parsed.errors, expectedDiagnostics);
});
}
@@ -28,11 +28,11 @@ namespace ts {
function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const fileText = JSON.stringify(json);
const { node, errors } = parseJsonText(configFileName, fileText);
assert(!errors.length);
assert(!!node);
const result = parseJsonText(configFileName, fileText);
assert(!result.parseDiagnostics.length);
assert(!!result.endOfFileToken);
const host: ParseConfigHost = new Utils.MockParseConfigHost("/apath/", true, []);
const { options: actualCompilerOptions, errors: actualParseErrors } = parseJsonNodeConfigFileContent(node, host, "/apath/", /*existingOptions*/ undefined, configFileName);
const { options: actualCompilerOptions, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName);
expectedResult.compilerOptions["configFilePath"] = configFileName;
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
@@ -40,11 +40,11 @@ namespace ts {
function assertTypeAcquisitionWithJsonNode(json: any, configFileName: string, expectedResult: ExpectedResult) {
const fileText = JSON.stringify(json);
const { node, errors } = parseJsonText(configFileName, fileText);
assert(!errors.length);
assert(!!node);
const result = parseJsonText(configFileName, fileText);
assert(!result.parseDiagnostics.length);
assert(!!result.endOfFileToken);
const host: ParseConfigHost = new Utils.MockParseConfigHost("/apath/", true, []);
const { typeAcquisition: actualTypeAcquisition, errors: actualParseErrors } = parseJsonNodeConfigFileContent(node, host, "/apath/", /*existingOptions*/ undefined, configFileName);
const { typeAcquisition: actualTypeAcquisition, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName);
verifyAcquisition(actualTypeAcquisition, expectedResult);
const actualErrors = filter(actualParseErrors, error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
+7 -2
View File
@@ -98,8 +98,13 @@ namespace ts {
function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
{
const jsonText = JSON.stringify(json);
const {node} = parseJsonText(caseInsensitiveTsconfigPath, jsonText);
const actual = ts.parseJsonNodeConfigFileContent(node, host, basePath, existingOptions, configFileName, resolutionStack);
const result = parseJsonText(caseInsensitiveTsconfigPath, jsonText);
const actual = ts.parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack);
for (const error of expected.errors) {
if (error.file) {
error.file = result;
}
}
assertParsed(actual, expected);
}
{
+5 -4
View File
@@ -23,7 +23,7 @@ namespace ts {
}
{
const parsed = ts.parseJsonText("/apath/tsconfig.json", jsonText);
const parsedCommand = ts.parseJsonNodeConfigFileContent(parsed.node, ts.sys, "tests/cases/unittests");
const parsedCommand = ts.parseJsonSourceFileConfigFileContent(parsed, ts.sys, "tests/cases/unittests");
assert.isTrue(parsedCommand.errors && parsedCommand.errors.length === 1 &&
parsedCommand.errors[0].code === ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code);
}
@@ -38,7 +38,7 @@ namespace ts {
function getParsedCommandJsonNode(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) {
const parsed = ts.parseJsonText(configFileName, jsonText);
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
return ts.parseJsonNodeConfigFileContent(parsed.node, host, basePath, /*existingOptions*/ undefined, configFileName);
return ts.parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName);
}
function assertParseFileList(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedFileList: string[]) {
@@ -231,8 +231,9 @@ namespace ts {
}
"files": ["file1.ts"]
}`;
const { node, errors: diagnostics } = parseJsonText("config.json", content);
const configJsonObject = convertToJson(node, diagnostics);
const result = parseJsonText("config.json", content);
const diagnostics = result.parseDiagnostics;
const configJsonObject = convertToJson(result, diagnostics);
const expectedResult = {
compilerOptions: {
allowJs: true,
+7 -7
View File
@@ -790,18 +790,18 @@ namespace ts.server {
return findProjectByName(projectFileName, this.externalProjects);
}
private getDefaultParsedJsonNode(): EndOfFileToken {
return <EndOfFileToken>{ kind: SyntaxKind.EndOfFileToken };
}
private convertConfigFileContentToProjectOptions(configFilename: string): ConfigFileConversionResult {
configFilename = normalizePath(configFilename);
const configFileContent = this.host.readFile(configFilename);
const { node = this.getDefaultParsedJsonNode(), errors } = parseJsonText(configFilename, configFileContent);
const parsedCommandLine = parseJsonNodeConfigFileContent(
node,
const result = parseJsonText(configFilename, configFileContent);
if (!result.endOfFileToken) {
result.endOfFileToken = <EndOfFileToken>{ kind: SyntaxKind.EndOfFileToken };
}
const errors = result.parseDiagnostics;
const parsedCommandLine = parseJsonSourceFileConfigFileContent(
result,
this.host,
getDirectoryPath(configFilename),
/*existingOptions*/ {},
+4 -4
View File
@@ -1135,25 +1135,25 @@ namespace ts {
const result = parseJsonText(fileName, text);
if (!result.node) {
if (!result.endOfFileToken) {
return {
options: {},
typeAcquisition: {},
files: [],
raw: {},
errors: realizeDiagnostics(result.errors, "\r\n")
errors: realizeDiagnostics(result.parseDiagnostics, "\r\n")
};
}
const normalizedFileName = normalizeSlashes(fileName);
const configFile = parseJsonNodeConfigFileContent(result.node, this.host, getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName);
const configFile = parseJsonSourceFileConfigFileContent(result, this.host, getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName);
return {
options: configFile.options,
typeAcquisition: configFile.typeAcquisition,
files: configFile.fileNames,
raw: configFile.raw,
errors: realizeDiagnostics(result.errors.concat(configFile.errors), "\r\n")
errors: realizeDiagnostics(result.parseDiagnostics.concat(configFile.errors), "\r\n")
};
});
}