diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 6d62d7b67d90a..acaa8283a2af2 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -27,6 +27,12 @@ namespace ts {
return symbol.id;
}
+ export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
+ const moduleState = getModuleInstanceState(node);
+ return moduleState === ModuleInstanceState.Instantiated ||
+ (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
+ }
+
export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker {
// Cancellation that controls whether or not we can cancel in the middle of type checking.
// In general cancelling is *not* safe for the type checker. We might be in the middle of
diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index a21c9bd5cd94c..7b508351aeccc 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -2,7 +2,7 @@
///
///
///
-///
+///
namespace ts {
/* @internal */
@@ -640,7 +640,7 @@ namespace ts {
];
/* @internal */
- export let typeAcquisitionDeclarations: CommandLineOption[] = [
+ export const typeAcquisitionDeclarations: CommandLineOption[] = [
{
/* @deprecated typingOptions.enableAutoDiscovery
* Use typeAcquisition.enable instead.
@@ -719,8 +719,12 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
+ return createDiagnosticForInvalidCustomType(opt, createCompilerDiagnostic);
+ }
+
+ function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic {
const namesOfType = arrayFrom(opt.type.keys()).map(key => `'${key}'`).join(", ");
- return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
+ return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}
/* @internal */
@@ -880,7 +884,7 @@ namespace ts {
text = readFile(fileName);
}
catch (e) {
- return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
+ return { config: {}, error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
}
return parseConfigFileTextToJson(fileName, text);
}
@@ -890,13 +894,306 @@ namespace ts {
* @param fileName The path to the config file
* @param jsonText The text of the config file
*/
- export function parseConfigFileTextToJson(fileName: string, jsonText: string, stripComments = true): { config?: any; error?: Diagnostic } {
+ export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
+ const jsonSourceFile = parseJsonText(fileName, jsonText);
+ return {
+ config: convertToObject(jsonSourceFile, jsonSourceFile.parseDiagnostics),
+ error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
+ };
+ }
+
+ /**
+ * Read tsconfig.json file
+ * @param fileName The path to the config file
+ */
+ export function readJsonConfigFile(fileName: string, readFile: (path: string) => string): JsonSourceFile {
+ let text = "";
try {
- const jsonTextToParse = stripComments ? removeComments(jsonText) : jsonText;
- return { config: /\S/.test(jsonTextToParse) ? JSON.parse(jsonTextToParse) : {} };
+ text = readFile(fileName);
}
catch (e) {
- return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
+ return { parseDiagnostics: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] };
+ }
+ return parseJsonText(fileName, text);
+ }
+
+ function commandLineOptionsToMap(options: CommandLineOption[]) {
+ return arrayToMap(options, option => option.name);
+ }
+
+ let _tsconfigRootOptions: Map;
+ function getTsconfigRootOptionsMap() {
+ if (_tsconfigRootOptions === undefined) {
+ _tsconfigRootOptions = commandLineOptionsToMap([
+ {
+ name: "compilerOptions",
+ type: "object",
+ elementOptions: commandLineOptionsToMap(optionDeclarations),
+ extraKeyDiagnosticMessage: Diagnostics.Unknown_compiler_option_0
+ },
+ {
+ name: "typingOptions",
+ type: "object",
+ elementOptions: commandLineOptionsToMap(typeAcquisitionDeclarations),
+ extraKeyDiagnosticMessage: Diagnostics.Unknown_type_acquisition_option_0
+ },
+ {
+ name: "typeAcquisition",
+ type: "object",
+ elementOptions: commandLineOptionsToMap(typeAcquisitionDeclarations),
+ extraKeyDiagnosticMessage: Diagnostics.Unknown_type_acquisition_option_0
+ },
+ {
+ name: "extends",
+ type: "string"
+ },
+ {
+ name: "files",
+ type: "list",
+ element: {
+ name: "files",
+ type: "string"
+ }
+ },
+ {
+ name: "include",
+ type: "list",
+ element: {
+ name: "include",
+ type: "string"
+ }
+ },
+ {
+ name: "exclude",
+ type: "list",
+ element: {
+ name: "exclude",
+ type: "string"
+ }
+ },
+ compileOnSaveCommandLineOption
+ ]);
+ }
+ return _tsconfigRootOptions;
+ }
+
+ interface JsonConversionNotifier {
+ /**
+ * Notifies parent option object is being set with the optionKey and a valid optionValue
+ * Currently it notifies only if there is element with type object (parentOption) and
+ * has element's option declarations map associated with it
+ * @param parentOption parent option name in which the option and value are being set
+ * @param option option declaration which is being set with the value
+ * @param value value of the option
+ */
+ onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue): void;
+ /**
+ * Notify when valid root key value option is being set
+ * @param key option key
+ * @param keyNode node corresponding to node in the source file
+ * @param value computed value of the key
+ * @param ValueNode node corresponding to value in the source file
+ */
+ onSetValidOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void;
+ /**
+ * Notify when unknown root key value option is being set
+ * @param key option key
+ * @param keyNode node corresponding to node in the source file
+ * @param value computed value of the key
+ * @param ValueNode node corresponding to value in the source file
+ */
+ onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void;
+ }
+
+ /**
+ * Convert the json syntax tree into the json value
+ */
+ export function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any {
+ return convertToObjectWorker(sourceFile, errors, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined);
+ }
+
+ /**
+ * Convert the json syntax tree into the json value
+ */
+ function convertToObjectWorker(
+ sourceFile: JsonSourceFile,
+ errors: Diagnostic[],
+ knownRootOptions: Map | undefined,
+ jsonConversionNotifier: JsonConversionNotifier | undefined): any {
+ if (!sourceFile.jsonObject) {
+ return {};
+ }
+
+ return convertObjectLiteralExpressionToJson(sourceFile.jsonObject, knownRootOptions,
+ /*extraKeyDiagnosticMessage*/ undefined, /*parentOption*/ undefined);
+
+ function convertObjectLiteralExpressionToJson(
+ node: ObjectLiteralExpression,
+ knownOptions: Map | undefined,
+ extraKeyDiagnosticMessage: DiagnosticMessage | undefined,
+ parentOption: string | undefined
+ ): any {
+ const result: any = {};
+ for (const element of node.properties) {
+ if (element.kind !== SyntaxKind.PropertyAssignment) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element, Diagnostics.Property_assignment_expected));
+ continue;
+ }
+
+ if (element.questionToken) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.questionToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "?"));
+ }
+ if (!isDoubleQuotedString(element.name)) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected));
+ }
+
+ const keyText = getTextOfPropertyName(element.name);
+ const option = knownOptions ? knownOptions.get(keyText) : undefined;
+ if (extraKeyDiagnosticMessage && !option) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnosticMessage, keyText));
+ }
+ const value = convertPropertyValueToJson(element.initializer, option);
+ if (typeof keyText !== undefined && typeof value !== undefined) {
+ result[keyText] = value;
+ // Notify key value set, if user asked for it
+ if (jsonConversionNotifier &&
+ // Current callbacks are only on known parent option or if we are setting values in the root
+ (parentOption || knownOptions === knownRootOptions)) {
+ const isValidOptionValue = isCompilerOptionsValue(option, value);
+ if (parentOption) {
+ if (isValidOptionValue) {
+ // Notify option set in the parent if its a valid option value
+ jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option, value);
+ }
+ }
+ else if (knownOptions === knownRootOptions) {
+ if (isValidOptionValue) {
+ // Notify about the valid root key value being set
+ jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer);
+ }
+ else if (!option) {
+ // Notify about the unknown root key value being set
+ jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ function convertArrayLiteralExpressionToJson(
+ elements: NodeArray,
+ elementOption: CommandLineOption | undefined
+ ): any[] {
+ const result: any[] = [];
+ for (const element of elements) {
+ result.push(convertPropertyValueToJson(element, elementOption));
+ }
+ return result;
+ }
+
+ function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption): any {
+ switch (valueExpression.kind) {
+ case SyntaxKind.TrueKeyword:
+ reportInvalidOptionValue(option && option.type !== "boolean");
+ return true;
+
+ case SyntaxKind.FalseKeyword:
+ reportInvalidOptionValue(option && option.type !== "boolean");
+ return false;
+
+ case SyntaxKind.NullKeyword:
+ reportInvalidOptionValue(!!option);
+ return null; // tslint:disable-line:no-null-keyword
+
+ case SyntaxKind.StringLiteral:
+ if (!isDoubleQuotedString(valueExpression)) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.String_literal_with_double_quotes_expected));
+ }
+ reportInvalidOptionValue(option && (typeof option.type === "string" && option.type !== "string"));
+ const text = (valueExpression).text;
+ if (option && typeof option.type !== "string") {
+ const customOption = option;
+ // Validate custom option type
+ if (!customOption.type.has(text)) {
+ errors.push(
+ createDiagnosticForInvalidCustomType(
+ customOption,
+ (message, arg0, arg1) => createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1)
+ )
+ );
+ }
+ }
+ return text;
+
+ case SyntaxKind.NumericLiteral:
+ reportInvalidOptionValue(option && option.type !== "number");
+ return Number((valueExpression).text);
+
+ case SyntaxKind.ObjectLiteralExpression:
+ reportInvalidOptionValue(option && option.type !== "object");
+ const objectLiteralExpression = valueExpression;
+
+ // Currently having element option declaration in the tsconfig with type "object"
+ // determines if it needs onSetValidOptionKeyValueInParent callback or not
+ // At moment there are only "compilerOptions", "typeAcquisition" and "typingOptions"
+ // that satifies it and need it to modify options set in them (for normalizing file paths)
+ // vs what we set in the json
+ // If need arises, we can modify this interface and callbacks as needed
+ if (option) {
+ const { elementOptions, extraKeyDiagnosticMessage, name: optionName } = option;
+ return convertObjectLiteralExpressionToJson(objectLiteralExpression,
+ elementOptions, extraKeyDiagnosticMessage, optionName);
+ }
+ else {
+ return convertObjectLiteralExpressionToJson(
+ objectLiteralExpression, /* knownOptions*/ undefined,
+ /*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined);
+ }
+
+ case SyntaxKind.ArrayLiteralExpression:
+ reportInvalidOptionValue(option && option.type !== "list");
+ return convertArrayLiteralExpressionToJson(
+ (valueExpression).elements,
+ option && (option).element);
+ }
+
+ // Not in expected format
+ if (option) {
+ reportInvalidOptionValue(/*isError*/ true);
+ }
+ else {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal));
+ }
+
+ return undefined;
+
+ function reportInvalidOptionValue(isError: boolean) {
+ if (isError) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option.name, getCompilerOptionValueTypeString(option)));
+ }
+ }
+ }
+
+ function isDoubleQuotedString(node: Node) {
+ return node.kind === SyntaxKind.StringLiteral && getSourceTextOfNodeFromSourceFile(sourceFile, node).charCodeAt(0) === CharacterCodes.doubleQuote;
+ }
+ }
+
+ function getCompilerOptionValueTypeString(option: CommandLineOption) {
+ return option.type === "list" ?
+ "Array" :
+ typeof option.type === "string" ? option.type : "string";
+ }
+
+ function isCompilerOptionsValue(option: CommandLineOption, value: any): value is CompilerOptionsValue {
+ if (option) {
+ if (option.type === "list") {
+ return isArray(value);
+ }
+ const expectedType = typeof option.type === "string" ? option.type : "string";
+ return typeof value === expectedType;
}
}
@@ -952,7 +1249,7 @@ namespace ts {
if (optionsNameMap.has(name) && optionsNameMap.get(name).category === Diagnostics.Command_line_Options) {
continue;
}
- const value = options[name];
+ const value = options[name];
const optionDefinition = optionsNameMap.get(name.toLowerCase());
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
@@ -1069,117 +1366,110 @@ namespace ts {
}
/**
- * Remove the comments from a json like text.
- * Comments can be single line comments (starting with # or //) or multiline comments using / * * /
- *
- * This method replace comment content by whitespace rather than completely remove them to keep positions in json parsing error reporting accurate.
+ * Parse the contents of a config file (tsconfig.json).
+ * @param json The contents of the config file to parse
+ * @param host Instance of ParseConfigHost used to enumerate files in folder.
+ * @param basePath A root directory to resolve relative path entries in the config
+ * file to. e.g. outDir
*/
- function removeComments(jsonText: string): string {
- let output = "";
- const scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText);
- let token: SyntaxKind;
- while ((token = scanner.scan()) !== SyntaxKind.EndOfFileToken) {
- switch (token) {
- case SyntaxKind.SingleLineCommentTrivia:
- case SyntaxKind.MultiLineCommentTrivia:
- // replace comments with whitespace to preserve original character positions
- output += scanner.getTokenText().replace(/\S/g, " ");
- break;
- default:
- output += scanner.getTokenText();
- break;
- }
- }
- return output;
+ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: JsFileExtensionInfo[]): ParsedCommandLine {
+ return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions);
}
/**
* Parse the contents of a config file (tsconfig.json).
+ * @param jsonNode The contents of the config file to parse
+ * @param host Instance of ParseConfigHost used to enumerate files in folder.
+ * @param basePath A root directory to resolve relative path entries in the config
+ * file to. e.g. outDir
+ */
+ export function parseJsonSourceFileConfigFileContent(sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: JsFileExtensionInfo[]): ParsedCommandLine {
+ return parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions);
+ }
+
+ /*@internal*/
+ export function setConfigFileInOptions(options: CompilerOptions, configFile: JsonSourceFile) {
+ if (configFile) {
+ Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile });
+ }
+ }
+
+ /**
+ * Parse the contents of a config file from json or json source file (tsconfig.json).
* @param json The contents of the config file to parse
+ * @param sourceFile sourceFile corresponding to the Json
* @param host Instance of ParseConfigHost used to enumerate files in folder.
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
* @param resolutionStack Only present for backwards-compatibility. Should be empty.
*/
- export function parseJsonConfigFileContent(
- json: any,
- host: ParseConfigHost,
- basePath: string,
- existingOptions: CompilerOptions = {},
- configFileName?: string,
- resolutionStack: Path[] = [],
- extraFileExtensions: JsFileExtensionInfo[] = [],
- ): ParsedCommandLine {
+ function parseJsonConfigFileContentWorker(
+ json: any,
+ sourceFile: JsonSourceFile,
+ host: ParseConfigHost,
+ basePath: string,
+ existingOptions: CompilerOptions = {},
+ configFileName?: string,
+ resolutionStack: Path[] = [],
+ extraFileExtensions: JsFileExtensionInfo[] = [],
+ ): ParsedCommandLine {
+ Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
const errors: Diagnostic[] = [];
- let options = (() => {
- const { include, exclude, files, options, compileOnSave } = parseConfig(json, host, basePath, configFileName, resolutionStack, errors);
- if (include) { json.include = include; }
- if (exclude) { json.exclude = exclude; }
- if (files) { json.files = files; }
- if (compileOnSave !== undefined) { json.compileOnSave = compileOnSave; }
- return options;
- })();
-
- options = extend(existingOptions, options);
+ const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors);
+ const { raw } = parsedConfig;
+ const options = extend(existingOptions, parsedConfig.options || {});
options.configFilePath = configFileName;
-
- // typingOptions has been deprecated and is only supported for backward compatibility purposes.
- // It should be removed in future releases - use typeAcquisition instead.
- const jsonOptions = json["typeAcquisition"] || json["typingOptions"];
- const typeAcquisition: TypeAcquisition = convertTypeAcquisitionFromJsonWorker(jsonOptions, basePath, errors, configFileName);
-
+ setConfigFileInOptions(options, sourceFile);
const { fileNames, wildcardDirectories } = getFileNames();
- const compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors);
-
return {
options,
fileNames,
- typeAcquisition,
- raw: json,
+ typeAcquisition: parsedConfig.typeAcquisition || getDefaultTypeAcquisition(),
+ raw,
errors,
wildcardDirectories,
- compileOnSave
+ compileOnSave: !!raw.compileOnSave
};
function getFileNames(): ExpandResult {
let fileNames: string[];
- if (hasProperty(json, "files")) {
- if (isArray(json["files"])) {
- fileNames = json["files"];
+ if (hasProperty(raw, "files")) {
+ if (isArray(raw["files"])) {
+ fileNames = raw["files"];
if (fileNames.length === 0) {
- errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
+ createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json");
}
}
else {
- errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array"));
+ createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array");
}
}
let includeSpecs: string[];
- if (hasProperty(json, "include")) {
- if (isArray(json["include"])) {
- includeSpecs = json["include"];
+ if (hasProperty(raw, "include")) {
+ if (isArray(raw["include"])) {
+ includeSpecs = raw["include"];
}
else {
- errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "include", "Array"));
+ createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "include", "Array");
}
}
let excludeSpecs: string[];
- if (hasProperty(json, "exclude")) {
- if (isArray(json["exclude"])) {
- excludeSpecs = json["exclude"];
+ if (hasProperty(raw, "exclude")) {
+ if (isArray(raw["exclude"])) {
+ excludeSpecs = raw["exclude"];
}
else {
- errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "exclude", "Array"));
+ createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "exclude", "Array");
}
}
else {
// If no includes were specified, exclude common package folders and the outDir
excludeSpecs = includeSpecs ? [] : ["node_modules", "bower_components", "jspm_packages"];
- const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
+ const outDir = raw["compilerOptions"] && raw["compilerOptions"]["outDir"];
if (outDir) {
excludeSpecs.push(outDir);
}
@@ -1189,9 +1479,9 @@ namespace ts {
includeSpecs = ["**/*"];
}
- const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, extraFileExtensions);
+ const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, extraFileExtensions, sourceFile);
- if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
+ if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0) {
errors.push(
createCompilerDiagnostic(
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
@@ -1202,14 +1492,23 @@ namespace ts {
return result;
}
+
+ function createCompilerDiagnosticOnlyIfJson(message: DiagnosticMessage, arg0?: string, arg1?: string) {
+ if (!sourceFile) {
+ errors.push(createCompilerDiagnostic(message, arg0, arg1));
+ }
+ }
}
interface ParsedTsconfig {
- include: string[] | undefined;
- exclude: string[] | undefined;
- files: string[] | undefined;
- options: CompilerOptions;
- compileOnSave: boolean | undefined;
+ raw: any;
+ options?: CompilerOptions;
+ typeAcquisition?: TypeAcquisition;
+ extendedConfigPath?: Path;
+ }
+
+ function isSuccessfulParsedTsconfig(value: ParsedTsconfig) {
+ return !!value.options;
}
/**
@@ -1218,94 +1517,223 @@ namespace ts {
*/
function parseConfig(
json: any,
+ sourceFile: JsonSourceFile,
host: ParseConfigHost,
basePath: string,
configFileName: string,
resolutionStack: Path[],
errors: Diagnostic[],
- ): ParsedTsconfig {
-
+ ): ParsedTsconfig {
basePath = normalizeSlashes(basePath);
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName);
if (resolutionStack.indexOf(resolvedPath) >= 0) {
errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> ")));
- return { include: undefined, exclude: undefined, files: undefined, options: {}, compileOnSave: undefined };
+ return { raw: json || convertToObject(sourceFile, errors) };
+ }
+
+ const ownConfig = json ?
+ parseOwnConfigOfJson(json, host, basePath, getCanonicalFileName, configFileName, errors) :
+ parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, getCanonicalFileName, configFileName, errors);
+
+ if (ownConfig.extendedConfigPath) {
+ // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
+ resolutionStack = resolutionStack.concat([resolvedPath]);
+ const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, getCanonicalFileName,
+ resolutionStack, errors);
+ if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
+ const baseRaw = extendedConfig.raw;
+ const raw = ownConfig.raw;
+ const setPropertyInRawIfNotUndefined = (propertyName: string) => {
+ const value = raw[propertyName] || baseRaw[propertyName];
+ if (value) {
+ raw[propertyName] = value;
+ }
+ };
+ setPropertyInRawIfNotUndefined("include");
+ setPropertyInRawIfNotUndefined("exclude");
+ setPropertyInRawIfNotUndefined("files");
+ if (raw.compileOnSave === undefined) {
+ raw.compileOnSave = baseRaw.compileOnSave;
+ }
+ ownConfig.options = assign({}, extendedConfig.options, ownConfig.options);
+ // TODO extend type typeAcquisition
+ }
}
+ return ownConfig;
+ }
+
+ function parseOwnConfigOfJson(
+ json: any,
+ host: ParseConfigHost,
+ basePath: string,
+ getCanonicalFileName: (fileName: string) => string,
+ configFileName: string,
+ errors: Diagnostic[]
+ ): ParsedTsconfig {
if (hasProperty(json, "excludes")) {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
}
- let options: CompilerOptions = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName);
- let include: string[] | undefined = json.include, exclude: string[] | undefined = json.exclude, files: string[] | undefined = json.files;
- let compileOnSave: boolean | undefined = json.compileOnSave;
+ const options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName);
+ // typingOptions has been deprecated and is only supported for backward compatibility purposes.
+ // It should be removed in future releases - use typeAcquisition instead.
+ const typeAcquisition = convertTypeAcquisitionFromJsonWorker(json["typeAcquisition"] || json["typingOptions"], basePath, errors, configFileName);
+ json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors);
+ let extendedConfigPath: Path;
if (json.extends) {
- // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
- resolutionStack = resolutionStack.concat([resolvedPath]);
- const base = getExtendedConfig(json.extends, host, basePath, getCanonicalFileName, resolutionStack, errors);
- if (base) {
- include = include || base.include;
- exclude = exclude || base.exclude;
- files = files || base.files;
- if (compileOnSave === undefined) {
- compileOnSave = base.compileOnSave;
- }
- options = assign({}, base.options, options);
+ if (typeof json.extends !== "string") {
+ errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string"));
+ }
+ else {
+ extendedConfigPath = getExtendsConfigPath(json.extends, host, basePath, getCanonicalFileName, errors, createCompilerDiagnostic);
}
}
-
- return { include, exclude, files, options, compileOnSave };
+ return { raw: json, options, typeAcquisition, extendedConfigPath };
}
- function getExtendedConfig(
- extended: any, // Usually a string.
- host: ts.ParseConfigHost,
- basePath: string,
- getCanonicalFileName: (fileName: string) => string,
- resolutionStack: Path[],
- errors: Diagnostic[],
- ): ParsedTsconfig | undefined {
- if (typeof extended !== "string") {
- errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string"));
- return undefined;
+ function parseOwnConfigOfJsonSourceFile(
+ sourceFile: JsonSourceFile,
+ host: ParseConfigHost,
+ basePath: string,
+ getCanonicalFileName: (fileName: string) => string,
+ configFileName: string,
+ errors: Diagnostic[]
+ ): ParsedTsconfig {
+ const options = getDefaultCompilerOptions(configFileName);
+ let typeAcquisition: TypeAcquisition, typingOptionstypeAcquisition: TypeAcquisition;
+ let extendedConfigPath: Path;
+
+ const optionsIterator: JsonConversionNotifier = {
+ onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue) {
+ Debug.assert(parentOption === "compilerOptions" || parentOption === "typeAcquisition" || parentOption === "typingOptions");
+ const currentOption = parentOption === "compilerOptions" ?
+ options :
+ parentOption === "typeAcquisition" ?
+ (typeAcquisition || (typeAcquisition = getDefaultTypeAcquisition(configFileName))) :
+ (typingOptionstypeAcquisition || (typingOptionstypeAcquisition = getDefaultTypeAcquisition(configFileName)));
+
+ currentOption[option.name] = normalizeOptionValue(option, basePath, value);
+ },
+ onSetValidOptionKeyValueInRoot(key: string, _keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression) {
+ switch (key) {
+ case "extends":
+ extendedConfigPath = getExtendsConfigPath(
+ value,
+ host,
+ basePath,
+ getCanonicalFileName,
+ errors,
+ (message, arg0) =>
+ createDiagnosticForNodeInSourceFile(sourceFile, valueNode, message, arg0)
+ );
+ return;
+ case "files":
+ if ((value).length === 0) {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueNode, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
+ }
+ return;
+ }
+ },
+ onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, _value: CompilerOptionsValue, _valueNode: Expression) {
+ if (key === "excludes") {
+ errors.push(createDiagnosticForNodeInSourceFile(sourceFile, keyNode, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
+ }
+ }
+ };
+ const json = convertToObjectWorker(sourceFile, errors, getTsconfigRootOptionsMap(), optionsIterator);
+ if (!typeAcquisition) {
+ if (typingOptionstypeAcquisition) {
+ typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ?
+ {
+ enable: typingOptionstypeAcquisition.enableAutoDiscovery,
+ include: typingOptionstypeAcquisition.include,
+ exclude: typingOptionstypeAcquisition.exclude
+ } :
+ typingOptionstypeAcquisition;
+ }
+ else {
+ typeAcquisition = getDefaultTypeAcquisition(configFileName);
+ }
}
- extended = normalizeSlashes(extended);
+ return { raw: json, options, typeAcquisition, extendedConfigPath };
+ }
+ function getExtendsConfigPath(
+ extendedConfig: string,
+ host: ParseConfigHost,
+ basePath: string,
+ getCanonicalFileName: (fileName: string) => string,
+ errors: Diagnostic[],
+ createDiagnostic: (message: DiagnosticMessage, arg1?: string) => Diagnostic) {
+ extendedConfig = normalizeSlashes(extendedConfig);
// If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future)
- if (!(isRootedDiskPath(extended) || startsWith(extended, "./") || startsWith(extended, "../"))) {
- errors.push(createCompilerDiagnostic(Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extended));
+ if (!(isRootedDiskPath(extendedConfig) || startsWith(extendedConfig, "./") || startsWith(extendedConfig, "../"))) {
+ errors.push(createDiagnostic(Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extendedConfig));
return undefined;
}
-
- let extendedConfigPath = toPath(extended, basePath, getCanonicalFileName);
+ let extendedConfigPath = toPath(extendedConfig, basePath, getCanonicalFileName);
if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, ".json")) {
- extendedConfigPath = extendedConfigPath + ".json" as Path;
+ extendedConfigPath = `${extendedConfigPath}.json` as Path;
if (!host.fileExists(extendedConfigPath)) {
- errors.push(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, extended));
+ errors.push(createDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig));
return undefined;
}
}
+ return extendedConfigPath;
+ }
- const extendedResult = readConfigFile(extendedConfigPath, path => host.readFile(path));
- if (extendedResult.error) {
- errors.push(extendedResult.error);
+ function getExtendedConfig(
+ sourceFile: JsonSourceFile,
+ extendedConfigPath: Path,
+ host: ts.ParseConfigHost,
+ basePath: string,
+ getCanonicalFileName: (fileName: string) => string,
+ resolutionStack: Path[],
+ errors: Diagnostic[],
+ ): ParsedTsconfig | undefined {
+ const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path));
+ if (sourceFile) {
+ (sourceFile.extendedSourceFiles || (sourceFile.extendedSourceFiles = [])).push(extendedResult.fileName);
+ }
+ if (extendedResult.parseDiagnostics.length) {
+ errors.push(...extendedResult.parseDiagnostics);
return undefined;
}
const extendedDirname = getDirectoryPath(extendedConfigPath);
- const relativeDifference = convertToRelativePath(extendedDirname, basePath, getCanonicalFileName);
- const updatePath: (path: string) => string = path => isRootedDiskPath(path) ? path : combinePaths(relativeDifference, path);
- const { include, exclude, files, options, compileOnSave } = parseConfig(extendedResult.config, host, extendedDirname, getBaseFileName(extendedConfigPath), resolutionStack, errors);
- return { include: map(include, updatePath), exclude: map(exclude, updatePath), files: map(files, updatePath), compileOnSave, options };
+ const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname,
+ getBaseFileName(extendedConfigPath), resolutionStack, errors);
+ if (sourceFile) {
+ sourceFile.extendedSourceFiles.push(...extendedResult.extendedSourceFiles);
+ }
+
+ if (isSuccessfulParsedTsconfig(extendedConfig)) {
+ // Update the paths to reflect base path
+ const relativeDifference = convertToRelativePath(extendedDirname, basePath, getCanonicalFileName);
+ const updatePath = (path: string) => isRootedDiskPath(path) ? path : combinePaths(relativeDifference, path);
+ const mapPropertiesInRawIfNotUndefined = (propertyName: string) => {
+ if (raw[propertyName]) {
+ raw[propertyName] = map(raw[propertyName], updatePath);
+ }
+ };
+
+ const { raw } = extendedConfig;
+ mapPropertiesInRawIfNotUndefined("include");
+ mapPropertiesInRawIfNotUndefined("exclude");
+ mapPropertiesInRawIfNotUndefined("files");
+ }
+
+ return extendedConfig;
}
- export function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean {
+ function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean {
if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) {
- return false;
+ return undefined;
}
const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption["compileOnSave"], basePath, errors);
if (typeof result === "boolean" && result) {
@@ -1326,20 +1754,30 @@ namespace ts {
return { options, errors };
}
- function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
- basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
-
+ function getDefaultCompilerOptions(configFileName?: string) {
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json"
? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true, skipLibCheck: true }
: {};
+ return options;
+ }
+
+ function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
+ basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
+
+ const options = getDefaultCompilerOptions(configFileName);
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
return options;
}
+ function getDefaultTypeAcquisition(configFileName?: string) {
+ const options: TypeAcquisition = { enable: getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
+ return options;
+ }
+
function convertTypeAcquisitionFromJsonWorker(jsonOptions: any,
basePath: string, errors: Diagnostic[], configFileName?: string): TypeAcquisition {
- const options: TypeAcquisition = { enable: getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
+ const options = getDefaultTypeAcquisition(configFileName);
const typeAcquisition = convertEnableAutoDiscoveryToEnable(jsonOptions);
convertOptionsFromJson(typeAcquisitionDeclarations, typeAcquisition, basePath, options, Diagnostics.Unknown_type_acquisition_option_0, errors);
@@ -1353,7 +1791,7 @@ namespace ts {
return;
}
- const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
+ const optionNameMap = commandLineOptionsToMap(optionDeclarations);
for (const id in jsonOptions) {
const opt = optionNameMap.get(id);
@@ -1367,28 +1805,43 @@ namespace ts {
}
function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): CompilerOptionsValue {
- const optType = opt.type;
- const expectedType = typeof optType === "string" ? optType : "string";
- if (optType === "list" && isArray(value)) {
- return convertJsonOptionOfListType(opt, value, basePath, errors);
- }
- else if (typeof value === expectedType) {
- if (typeof optType !== "string") {
- return convertJsonOptionOfCustomType(opt, value, errors);
+ if (isCompilerOptionsValue(opt, value)) {
+ const optType = opt.type;
+ if (optType === "list" && isArray(value)) {
+ return convertJsonOptionOfListType(opt, value, basePath, errors);
}
- else {
- if (opt.isFilePath) {
- value = normalizePath(combinePaths(basePath, value));
- if (value === "") {
- value = ".";
- }
- }
+ else if (typeof optType !== "string") {
+ return convertJsonOptionOfCustomType(opt, value, errors);
}
- return value;
+ return normalizeNonListOptionValue(opt, basePath, value);
}
else {
- errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, expectedType));
+ errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, getCompilerOptionValueTypeString(opt)));
+ }
+ }
+
+ function normalizeOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
+ if (option.type === "list") {
+ const listOption = option;
+ if (listOption.element.isFilePath || typeof listOption.element.type !== "string") {
+ return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => !!v);
+ }
+ return value;
}
+ else if (typeof option.type !== "string") {
+ return option.type.get(value);
+ }
+ return normalizeNonListOptionValue(option, basePath, value);
+ }
+
+ function normalizeNonListOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
+ if (option.isFilePath) {
+ value = normalizePath(combinePaths(basePath, value));
+ if (value === "") {
+ value = ".";
+ }
+ }
+ return value;
}
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
@@ -1493,7 +1946,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[], extraFileExtensions: JsFileExtensionInfo[]): ExpandResult {
+ function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], extraFileExtensions: JsFileExtensionInfo[], jsonSourceFile: JsonSourceFile): ExpandResult {
basePath = normalizePath(basePath);
// The exclude spec list is converted into a regular expression, which allows us to quickly
@@ -1512,11 +1965,11 @@ namespace ts {
const wildcardFileMap = createMap();
if (include) {
- include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
+ include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false, jsonSourceFile, "include");
}
if (exclude) {
- exclude = validateSpecs(exclude, errors, /*allowTrailingRecursion*/ true);
+ exclude = validateSpecs(exclude, errors, /*allowTrailingRecursion*/ true, jsonSourceFile, "exclude");
}
// Wildcard directories (provided as part of a wildcard path) are stored in a
@@ -1571,17 +2024,17 @@ namespace ts {
};
}
- function validateSpecs(specs: string[], errors: Diagnostic[], allowTrailingRecursion: boolean) {
+ 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)) {
- errors.push(createCompilerDiagnostic(Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
+ errors.push(createDiagnostic(Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
}
else if (invalidMultipleRecursionPatterns.test(spec)) {
- errors.push(createCompilerDiagnostic(Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, spec));
+ errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, spec));
}
else if (invalidDotDotAfterRecursiveWildcardPattern.test(spec)) {
- errors.push(createCompilerDiagnostic(Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
+ errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
}
else {
validSpecs.push(spec);
@@ -1589,6 +2042,21 @@ namespace ts {
}
return validSpecs;
+
+ function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
+ if (jsonSourceFile && jsonSourceFile.jsonObject) {
+ for (const property of getPropertyAssignment(jsonSourceFile.jsonObject, specKey)) {
+ if (isArrayLiteralExpression(property.initializer)) {
+ for (const element of property.initializer.elements) {
+ if (element.kind === SyntaxKind.StringLiteral && (element).text === spec) {
+ return createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec);
+ }
+ }
+ }
+ }
+ }
+ return createCompilerDiagnostic(message, spec);
+ }
}
/**
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index 82b40c6231ac3..8e5bf01792471 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -2139,6 +2139,8 @@ namespace ts {
return ScriptKind.TS;
case Extension.Tsx:
return ScriptKind.TSX;
+ case ".json":
+ return ScriptKind.JSON;
default:
return ScriptKind.Unknown;
}
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 2854bb8f2ef68..c5c90dc627828 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -1,4 +1,4 @@
-{
+{
"Unterminated string literal.": {
"category": "Error",
"code": 1002
@@ -899,6 +899,14 @@
"category": "Error",
"code": 1326
},
+ "String literal with double quotes expected.": {
+ "category": "Error",
+ "code": 1327
+ },
+ "Property value can only be string literal, numeric literal, 'true', 'false', 'null', object literal or array literal.": {
+ "category": "Error",
+ "code": 1328
+ },
"Duplicate identifier '{0}'.": {
"category": "Error",
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index a788bf6a4d057..65cbee9873a35 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -8,6 +8,70 @@ namespace ts {
const delimiters = createDelimiterMap();
const brackets = createBracketsMap();
+ /*@internal*/
+ /**
+ * Iterates over the source files that are expected to have an emit output.
+ *
+ * @param host An EmitHost.
+ * @param action The action to execute.
+ * @param sourceFilesOrTargetSourceFile
+ * If an array, the full list of source files to emit.
+ * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
+ */
+ export function forEachEmittedFile(
+ host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void,
+ sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile,
+ emitOnlyDtsFiles?: boolean) {
+
+ const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
+ const options = host.getCompilerOptions();
+ if (options.outFile || options.out) {
+ if (sourceFiles.length) {
+ const jsFilePath = options.outFile || options.out;
+ const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
+ const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : "";
+ action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles);
+ }
+ }
+ else {
+ for (const sourceFile of sourceFiles) {
+ const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
+ const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
+ const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
+ action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles);
+ }
+ }
+ }
+
+ function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
+ return options.sourceMap ? jsFilePath + ".map" : undefined;
+ }
+
+ // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
+ // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
+ // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
+ function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): Extension {
+ if (options.jsx === JsxEmit.Preserve) {
+ if (isSourceFileJavaScript(sourceFile)) {
+ if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) {
+ return Extension.Jsx;
+ }
+ }
+ else if (sourceFile.languageVariant === LanguageVariant.JSX) {
+ // TypeScript source file preserving JSX syntax
+ return Extension.Jsx;
+ }
+ }
+ return Extension.Js;
+ }
+
+ function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) {
+ if (sourceFileOrBundle.kind === SyntaxKind.Bundle) {
+ return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile));
+ }
+ return getOriginalSourceFile(sourceFileOrBundle);
+ }
+
/*@internal*/
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[]): EmitResult {
diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts
index 32244a8679265..ed3ed36e79a03 100644
--- a/src/compiler/factory.ts
+++ b/src/compiler/factory.ts
@@ -2287,14 +2287,6 @@ namespace ts {
return range;
}
- /**
- * Gets flags that control emit behavior of a node.
- */
- export function getEmitFlags(node: Node): EmitFlags | undefined {
- const emitNode = node.emitNode;
- return emitNode && emitNode.flags;
- }
-
/**
* Sets flags that control emit behavior of a node.
*/
@@ -3809,16 +3801,6 @@ namespace ts {
return node;
}
- export function skipPartiallyEmittedExpressions(node: Expression): Expression;
- export function skipPartiallyEmittedExpressions(node: Node): Node;
- export function skipPartiallyEmittedExpressions(node: Node) {
- while (node.kind === SyntaxKind.PartiallyEmittedExpression) {
- node = (node).expression;
- }
-
- return node;
- }
-
function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) {
switch (outerExpression.kind) {
case SyntaxKind.ParenthesizedExpression: return updateParen(outerExpression, expression);
@@ -4239,177 +4221,4 @@ namespace ts {
Debug.assertNode(node, isExpression);
return node;
}
-
- export interface ExternalModuleInfo {
- externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
- externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
- exportSpecifiers: Map; // export specifiers by name
- exportedBindings: Identifier[][]; // exported names of local declarations
- exportedNames: Identifier[]; // all exported names local to module
- exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
- hasExportStarsToExportValues: boolean; // whether this module contains export*
- }
-
- export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
- const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
- const exportSpecifiers = createMultiMap();
- const exportedBindings: Identifier[][] = [];
- const uniqueExports = createMap();
- let exportedNames: Identifier[];
- let hasExportDefault = false;
- let exportEquals: ExportAssignment = undefined;
- let hasExportStarsToExportValues = false;
-
- for (const node of sourceFile.statements) {
- switch (node.kind) {
- case SyntaxKind.ImportDeclaration:
- // import "mod"
- // import x from "mod"
- // import * as x from "mod"
- // import { x, y } from "mod"
- externalImports.push(node);
- break;
-
- case SyntaxKind.ImportEqualsDeclaration:
- if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
- // import x = require("mod")
- externalImports.push(node);
- }
-
- break;
-
- case SyntaxKind.ExportDeclaration:
- if ((node).moduleSpecifier) {
- if (!(node).exportClause) {
- // export * from "mod"
- externalImports.push(node);
- hasExportStarsToExportValues = true;
- }
- else {
- // export { x, y } from "mod"
- externalImports.push(node);
- }
- }
- else {
- // export { x, y }
- for (const specifier of (node).exportClause.elements) {
- if (!uniqueExports.get(specifier.name.text)) {
- const name = specifier.propertyName || specifier.name;
- exportSpecifiers.add(name.text, specifier);
-
- const decl = resolver.getReferencedImportDeclaration(name)
- || resolver.getReferencedValueDeclaration(name);
-
- if (decl) {
- multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
- }
-
- uniqueExports.set(specifier.name.text, true);
- exportedNames = append(exportedNames, specifier.name);
- }
- }
- }
- break;
-
- case SyntaxKind.ExportAssignment:
- if ((node).isExportEquals && !exportEquals) {
- // export = x
- exportEquals = node;
- }
- break;
-
- case SyntaxKind.VariableStatement:
- if (hasModifier(node, ModifierFlags.Export)) {
- for (const decl of (node).declarationList.declarations) {
- exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames);
- }
- }
- break;
-
- case SyntaxKind.FunctionDeclaration:
- if (hasModifier(node, ModifierFlags.Export)) {
- if (hasModifier(node, ModifierFlags.Default)) {
- // export default function() { }
- if (!hasExportDefault) {
- multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node));
- hasExportDefault = true;
- }
- }
- else {
- // export function x() { }
- const name = (node).name;
- if (!uniqueExports.get(name.text)) {
- multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
- uniqueExports.set(name.text, true);
- exportedNames = append(exportedNames, name);
- }
- }
- }
- break;
-
- case SyntaxKind.ClassDeclaration:
- if (hasModifier(node, ModifierFlags.Export)) {
- if (hasModifier(node, ModifierFlags.Default)) {
- // export default class { }
- if (!hasExportDefault) {
- multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node));
- hasExportDefault = true;
- }
- }
- else {
- // export class x { }
- const name = (node).name;
- if (!uniqueExports.get(name.text)) {
- multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
- uniqueExports.set(name.text, true);
- exportedNames = append(exportedNames, name);
- }
- }
- }
- break;
- }
- }
-
- const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues);
- const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
- createLiteral(externalHelpersModuleNameText));
-
- if (externalHelpersImportDeclaration) {
- externalImports.unshift(externalHelpersImportDeclaration);
- }
-
- return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
- }
-
- function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[]) {
- if (isBindingPattern(decl.name)) {
- for (const element of decl.name.elements) {
- if (!isOmittedExpression(element)) {
- exportedNames = collectExportedVariableInfo(element, uniqueExports, exportedNames);
- }
- }
- }
- else if (!isGeneratedIdentifier(decl.name)) {
- if (!uniqueExports.get(decl.name.text)) {
- uniqueExports.set(decl.name.text, true);
- exportedNames = append(exportedNames, decl.name);
- }
- }
- return exportedNames;
- }
-
- /** Use a sparse array as a multi-map. */
- function multiMapSparseArrayAdd(map: V[][], key: number, value: V): V[] {
- let values = map[key];
- if (values) {
- values.push(value);
- }
- else {
- map[key] = values = [value];
- }
- return values;
- }
}
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index e893dd600a878..0f08d6779107f 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -1,6 +1,5 @@
///
///
-///
namespace ts {
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
@@ -466,6 +465,15 @@ namespace ts {
return Parser.parseIsolatedEntityName(text, languageVersion);
}
+ /**
+ * Parse json text into SyntaxTree and return node and parse errors if any
+ * @param fileName
+ * @param sourceText
+ */
+ export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
+ return Parser.parseJsonText(fileName, sourceText);
+ }
+
// See also `isExternalOrCommonJsModule` in utilities.ts
export function isExternalModule(file: SourceFile): boolean {
return file.externalModuleIndicator !== undefined;
@@ -632,9 +640,34 @@ namespace ts {
return isInvalid ? entityName : undefined;
}
+ 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 = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON);
+ const result = sourceFile;
+
+ // Prime the scanner.
+ nextToken();
+ if (token() === SyntaxKind.EndOfFileToken) {
+ sourceFile.endOfFileToken = parseTokenNode();
+ }
+ else if (token() === SyntaxKind.OpenBraceToken ||
+ lookAhead(() => token() === SyntaxKind.StringLiteral)) {
+ result.jsonObject = parseObjectLiteralExpression();
+ sourceFile.endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, /*reportAtCurrentPosition*/ false, Diagnostics.Unexpected_token);
+ }
+ else {
+ parseExpected(SyntaxKind.OpenBraceToken);
+ }
+
+ sourceFile.parseDiagnostics = parseDiagnostics;
+ clearState();
+ 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) {
@@ -652,7 +685,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.
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index cc6ae1a5813ab..bbc0fa0978090 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -442,6 +442,7 @@ namespace ts {
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createFileMap(getCanonicalFileName);
+ let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression;
let moduleResolutionCache: ModuleResolutionCache;
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModuleFull[];
@@ -1328,7 +1329,11 @@ namespace ts {
function getOptionsDiagnostics(): Diagnostic[] {
return sortAndDeduplicateDiagnostics(concatenate(
fileProcessingDiagnostics.getGlobalDiagnostics(),
- programDiagnostics.getGlobalDiagnostics()));
+ concatenate(
+ programDiagnostics.getGlobalDiagnostics(),
+ options.configFile ? programDiagnostics.getDiagnostics(options.configFile.fileName) : []
+ )
+ ));
}
function getGlobalDiagnostics(): Diagnostic[] {
@@ -1773,33 +1778,33 @@ namespace ts {
function verifyCompilerOptions() {
if (options.isolatedModules) {
if (options.declaration) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules");
}
if (options.noEmitOnError) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules");
}
if (options.out) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules");
}
if (options.outFile) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules");
}
}
if (options.inlineSourceMap) {
if (options.sourceMap) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap");
}
if (options.mapRoot) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap");
}
}
if (options.paths && options.baseUrl === undefined) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option));
+ createDiagnosticForOptionName(Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option, "paths");
}
if (options.paths) {
@@ -1808,63 +1813,65 @@ namespace ts {
continue;
}
if (!hasZeroOrOneAsteriskCharacter(key)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key));
+ createDiagnosticForOptionPaths(/*onKey*/ true, key, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key);
}
if (isArray(options.paths[key])) {
- if (options.paths[key].length === 0) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key));
+ const len = options.paths[key].length;
+ if (len === 0) {
+ createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key);
}
- for (const subst of options.paths[key]) {
+ for (let i = 0; i < len; i++) {
+ const subst = options.paths[key][i];
const typeOfSubst = typeof subst;
if (typeOfSubst === "string") {
if (!hasZeroOrOneAsteriskCharacter(subst)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key));
+ createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key);
}
}
else {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst));
+ createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst);
}
}
}
else {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key));
+ createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key);
}
}
}
if (!options.sourceMap && !options.inlineSourceMap) {
if (options.inlineSources) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources");
}
if (options.sourceRoot) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot");
}
}
if (options.out && options.outFile) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile");
}
if (options.mapRoot && !options.sourceMap) {
// Error to specify --mapRoot without --sourcemap
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap");
}
if (options.declarationDir) {
if (!options.declaration) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration");
}
if (options.out || options.outFile) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile");
}
}
if (options.lib && options.noLib) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib");
}
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict");
}
const languageVersion = options.target || ScriptTarget.ES3;
@@ -1873,7 +1880,7 @@ namespace ts {
const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !f.isDeclarationFile ? f : undefined);
if (options.isolatedModules) {
if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher));
+ createDiagnosticForOptionName(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target");
}
const firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !f.isDeclarationFile ? f : undefined);
@@ -1891,7 +1898,7 @@ namespace ts {
// Cannot specify module gen that isn't amd or system with --out
if (outFile) {
if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile"));
+ createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module");
}
else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) {
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
@@ -1910,12 +1917,12 @@ namespace ts {
// If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure
if (options.outDir && dir === "" && forEach(files, file => getRootLength(file.fileName) > 1)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
+ createDiagnosticForOptionName(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir");
}
}
if (!options.noEmit && options.allowJs && options.declaration) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration");
}
if (options.checkJs && !options.allowJs) {
@@ -1924,19 +1931,19 @@ namespace ts {
if (options.emitDecoratorMetadata &&
!options.experimentalDecorators) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators");
}
if (options.jsxFactory) {
if (options.reactNamespace) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"));
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory");
}
if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory));
+ createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory);
}
}
else if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) {
- programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace));
+ createOptionValueDiagnostic("reactNamespace", Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace);
}
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
@@ -1976,6 +1983,91 @@ namespace ts {
}
}
+ function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, arg0: string | number, arg1: string | number, arg2?: string | number) {
+ let needCompilerDiagnostic = true;
+ const pathsSyntax = getOptionPathsSyntax();
+ for (const pathProp of pathsSyntax) {
+ if (isObjectLiteralExpression(pathProp.initializer)) {
+ for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) {
+ if (isArrayLiteralExpression(keyProps.initializer) &&
+ keyProps.initializer.elements.length > valueIndex) {
+ programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, keyProps.initializer.elements[valueIndex], message, arg0, arg1, arg2));
+ needCompilerDiagnostic = false;
+ }
+ }
+ }
+ }
+
+ if (needCompilerDiagnostic) {
+ programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1, arg2));
+ }
+ }
+
+ function createDiagnosticForOptionPaths(onKey: boolean, key: string, message: DiagnosticMessage, arg0: string | number) {
+ let needCompilerDiagnostic = true;
+ const pathsSyntax = getOptionPathsSyntax();
+ for (const pathProp of pathsSyntax) {
+ if (isObjectLiteralExpression(pathProp.initializer) &&
+ createOptionDiagnosticInObjectLiteralSyntax(
+ pathProp.initializer, onKey, key, /*key2*/ undefined,
+ message, arg0)) {
+ needCompilerDiagnostic = false;
+ }
+ }
+ if (needCompilerDiagnostic) {
+ programDiagnostics.add(createCompilerDiagnostic(message, arg0));
+ }
+ }
+
+ function getOptionPathsSyntax() {
+ const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
+ if (compilerOptionsObjectLiteralSyntax) {
+ return getPropertyAssignment(compilerOptionsObjectLiteralSyntax, "paths");
+ }
+ return emptyArray;
+ }
+
+ function createDiagnosticForOptionName(message: DiagnosticMessage, option1: string, option2?: string) {
+ createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2);
+ }
+
+ function createOptionValueDiagnostic(option1: string, message: DiagnosticMessage, arg0: string) {
+ createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0);
+ }
+
+ function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number) {
+ const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
+ const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax ||
+ !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1);
+
+ if (needCompilerDiagnostic) {
+ programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1));
+ }
+ }
+
+ function getCompilerOptionsObjectLiteralSyntax() {
+ if (_compilerOptionsObjectLiteralSyntax === undefined) {
+ _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword
+ if (options.configFile && options.configFile.jsonObject) {
+ for (const prop of getPropertyAssignment(options.configFile.jsonObject, "compilerOptions")) {
+ if (isObjectLiteralExpression(prop.initializer)) {
+ _compilerOptionsObjectLiteralSyntax = prop.initializer;
+ break;
+ }
+ }
+ }
+ }
+ return _compilerOptionsObjectLiteralSyntax;
+ }
+
+ function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number): boolean {
+ const props = getPropertyAssignment(objectLiteral, key1, key2);
+ for (const prop of props) {
+ programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, onKey ? prop.name : prop.initializer, message, arg0, arg1));
+ }
+ return !!props.length;
+ }
+
function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) {
hasEmitBlockingDiagnostics.set(toPath(emitFileName, currentDirectory, getCanonicalFileName), true);
programDiagnostics.add(diag);
diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts
index bfd3360e885c6..d61195ad74b54 100644
--- a/src/compiler/transformer.ts
+++ b/src/compiler/transformer.ts
@@ -1,4 +1,5 @@
///
+///
///
///
///
diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts
new file mode 100644
index 0000000000000..a39115a788e92
--- /dev/null
+++ b/src/compiler/transformers/utilities.ts
@@ -0,0 +1,180 @@
+/* @internal */
+namespace ts {
+ export function getOriginalNodeId(node: Node) {
+ node = getOriginalNode(node);
+ return node ? getNodeId(node) : 0;
+ }
+
+ export interface ExternalModuleInfo {
+ externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
+ externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
+ exportSpecifiers: Map; // export specifiers by name
+ exportedBindings: Identifier[][]; // exported names of local declarations
+ exportedNames: Identifier[]; // all exported names local to module
+ exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
+ hasExportStarsToExportValues: boolean; // whether this module contains export*
+ }
+
+ export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
+ const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
+ const exportSpecifiers = createMultiMap();
+ const exportedBindings: Identifier[][] = [];
+ const uniqueExports = createMap();
+ let exportedNames: Identifier[];
+ let hasExportDefault = false;
+ let exportEquals: ExportAssignment = undefined;
+ let hasExportStarsToExportValues = false;
+
+ for (const node of sourceFile.statements) {
+ switch (node.kind) {
+ case SyntaxKind.ImportDeclaration:
+ // import "mod"
+ // import x from "mod"
+ // import * as x from "mod"
+ // import { x, y } from "mod"
+ externalImports.push(node);
+ break;
+
+ case SyntaxKind.ImportEqualsDeclaration:
+ if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
+ // import x = require("mod")
+ externalImports.push(node);
+ }
+
+ break;
+
+ case SyntaxKind.ExportDeclaration:
+ if ((node).moduleSpecifier) {
+ if (!(node).exportClause) {
+ // export * from "mod"
+ externalImports.push(node);
+ hasExportStarsToExportValues = true;
+ }
+ else {
+ // export { x, y } from "mod"
+ externalImports.push(node);
+ }
+ }
+ else {
+ // export { x, y }
+ for (const specifier of (node).exportClause.elements) {
+ if (!uniqueExports.get(specifier.name.text)) {
+ const name = specifier.propertyName || specifier.name;
+ exportSpecifiers.add(name.text, specifier);
+
+ const decl = resolver.getReferencedImportDeclaration(name)
+ || resolver.getReferencedValueDeclaration(name);
+
+ if (decl) {
+ multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
+ }
+
+ uniqueExports.set(specifier.name.text, true);
+ exportedNames = append(exportedNames, specifier.name);
+ }
+ }
+ }
+ break;
+
+ case SyntaxKind.ExportAssignment:
+ if ((node).isExportEquals && !exportEquals) {
+ // export = x
+ exportEquals = node;
+ }
+ break;
+
+ case SyntaxKind.VariableStatement:
+ if (hasModifier(node, ModifierFlags.Export)) {
+ for (const decl of (node).declarationList.declarations) {
+ exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames);
+ }
+ }
+ break;
+
+ case SyntaxKind.FunctionDeclaration:
+ if (hasModifier(node, ModifierFlags.Export)) {
+ if (hasModifier(node, ModifierFlags.Default)) {
+ // export default function() { }
+ if (!hasExportDefault) {
+ multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node));
+ hasExportDefault = true;
+ }
+ }
+ else {
+ // export function x() { }
+ const name = (node).name;
+ if (!uniqueExports.get(name.text)) {
+ multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
+ uniqueExports.set(name.text, true);
+ exportedNames = append(exportedNames, name);
+ }
+ }
+ }
+ break;
+
+ case SyntaxKind.ClassDeclaration:
+ if (hasModifier(node, ModifierFlags.Export)) {
+ if (hasModifier(node, ModifierFlags.Default)) {
+ // export default class { }
+ if (!hasExportDefault) {
+ multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node));
+ hasExportDefault = true;
+ }
+ }
+ else {
+ // export class x { }
+ const name = (node).name;
+ if (!uniqueExports.get(name.text)) {
+ multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
+ uniqueExports.set(name.text, true);
+ exportedNames = append(exportedNames, name);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues);
+ const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
+ /*decorators*/ undefined,
+ /*modifiers*/ undefined,
+ createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
+ createLiteral(externalHelpersModuleNameText));
+
+ if (externalHelpersImportDeclaration) {
+ externalImports.unshift(externalHelpersImportDeclaration);
+ }
+
+ return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
+ }
+
+ function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[]) {
+ if (isBindingPattern(decl.name)) {
+ for (const element of decl.name.elements) {
+ if (!isOmittedExpression(element)) {
+ exportedNames = collectExportedVariableInfo(element, uniqueExports, exportedNames);
+ }
+ }
+ }
+ else if (!isGeneratedIdentifier(decl.name)) {
+ if (!uniqueExports.get(decl.name.text)) {
+ uniqueExports.set(decl.name.text, true);
+ exportedNames = append(exportedNames, decl.name);
+ }
+ }
+ return exportedNames;
+ }
+
+ /** Use a sparse array as a multi-map. */
+ function multiMapSparseArrayAdd(map: V[][], key: number, value: V): V[] {
+ let values = map[key];
+ if (values) {
+ values.push(value);
+ }
+ else {
+ map[key] = values = [value];
+ }
+ return values;
+ }
+}
\ No newline at end of file
diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts
index 637cfd0f16577..3b2422bfe089b 100644
--- a/src/compiler/tsc.ts
+++ b/src/compiler/tsc.ts
@@ -223,20 +223,13 @@ namespace ts {
return;
}
- const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText);
- const configObject = result.config;
- if (!configObject) {
- reportDiagnostics([result.error], /* compilerHost */ undefined);
- sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
- return;
- }
+ const result = parseJsonText(configFileName, cachedConfigFileText);
+ reportDiagnostics(result.parseDiagnostics, /* compilerHost */ undefined);
+
const cwd = sys.getCurrentDirectory();
- const configParseResult = parseJsonConfigFileContent(configObject, 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);
- return;
- }
+ const configParseResult = parseJsonSourceFileConfigFileContent(result, sys, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), commandLine.options, getNormalizedAbsolutePath(configFileName, cwd));
+ reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
+
if (isWatchSet(configParseResult.options)) {
if (!sys.watchFile) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined);
diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json
index 52bb92ee1f003..e896f4f2978e4 100644
--- a/src/compiler/tsconfig.json
+++ b/src/compiler/tsconfig.json
@@ -17,6 +17,7 @@
"checker.ts",
"factory.ts",
"visitor.ts",
+ "transformers/utilities.ts",
"transformers/ts.ts",
"transformers/jsx.ts",
"transformers/esnext.ts",
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 76be7b20b1da2..ac64624e1a6aa 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2375,6 +2375,11 @@ namespace ts {
sourceFiles: SourceFile[];
}
+ export interface JsonSourceFile extends SourceFile {
+ jsonObject?: ObjectLiteralExpression;
+ extendedSourceFiles?: string[];
+ }
+
export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
getSourceFile(fileName: string): SourceFile;
@@ -3488,6 +3493,7 @@ namespace ts {
charset?: string;
checkJs?: boolean;
/* @internal */ configFilePath?: string;
+ /* @internal */ readonly configFile?: JsonSourceFile;
declaration?: boolean;
declarationDir?: string;
/* @internal */ diagnostics?: boolean;
@@ -3560,7 +3566,7 @@ namespace ts {
/*@internal*/ version?: boolean;
/*@internal*/ watch?: boolean;
- [option: string]: CompilerOptionsValue | undefined;
+ [option: string]: CompilerOptionsValue | JsonSourceFile | undefined;
}
export interface TypeAcquisition {
@@ -3620,7 +3626,8 @@ namespace ts {
JSX = 2,
TS = 3,
TSX = 4,
- External = 5
+ External = 5,
+ JSON = 6
}
export const enum ScriptTarget {
@@ -3692,6 +3699,8 @@ namespace ts {
/* @internal */
export interface TsConfigOnlyOption extends CommandLineOptionBase {
type: "object";
+ elementOptions?: Map;
+ extraKeyDiagnosticMessage?: DiagnosticMessage;
}
/* @internal */
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 3833fc3087544..c8827801e5e07 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -309,6 +309,14 @@ namespace ts {
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia);
}
+ /**
+ * Gets flags that control emit behavior of a node.
+ */
+ export function getEmitFlags(node: Node): EmitFlags | undefined {
+ const emitNode = node.emitNode;
+ return emitNode && emitNode.flags;
+ }
+
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) {
// If we don't need to downlevel and we can reach the original source text using
// the node's parent reference, then simply get the text as it was originally written.
@@ -882,6 +890,15 @@ namespace ts {
return predicate && predicate.kind === TypePredicateKind.This;
}
+ export function getPropertyAssignment(objectLiteral: ObjectLiteralExpression, key: string, key2?: string) {
+ return filter(objectLiteral.properties, property => {
+ if (property.kind === SyntaxKind.PropertyAssignment) {
+ const propName = getTextOfPropertyName(property.name);
+ return key === propName || (key2 && key2 === propName);
+ }
+ });
+ }
+
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;
@@ -1242,12 +1259,6 @@ namespace ts {
return false;
}
- export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
- const moduleState = getModuleInstanceState(node);
- return moduleState === ModuleInstanceState.Instantiated ||
- (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
- }
-
export function isExternalModuleImportEqualsDeclaration(node: Node) {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
}
@@ -2013,14 +2024,7 @@ namespace ts {
|| positionIsSynthesized(node.end);
}
- export function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) {
- if (sourceFileOrBundle.kind === SyntaxKind.Bundle) {
- return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile));
- }
- return getOriginalSourceFile(sourceFileOrBundle);
- }
-
- function getOriginalSourceFile(sourceFile: SourceFile) {
+ export function getOriginalSourceFile(sourceFile: SourceFile) {
return getParseTreeNode(sourceFile, isSourceFile) || sourceFile;
}
@@ -2028,11 +2032,6 @@ namespace ts {
return sameMap(sourceFiles, getOriginalSourceFile);
}
- export function getOriginalNodeId(node: Node) {
- node = getOriginalNode(node);
- return node ? getNodeId(node) : 0;
- }
-
export const enum Associativity {
Left,
Right
@@ -2540,62 +2539,6 @@ namespace ts {
return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile);
}
- /**
- * Iterates over the source files that are expected to have an emit output.
- *
- * @param host An EmitHost.
- * @param action The action to execute.
- * @param sourceFilesOrTargetSourceFile
- * If an array, the full list of source files to emit.
- * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
- */
- export function forEachEmittedFile(
- host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void,
- sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile,
- emitOnlyDtsFiles?: boolean) {
-
- const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
- const options = host.getCompilerOptions();
- if (options.outFile || options.out) {
- if (sourceFiles.length) {
- const jsFilePath = options.outFile || options.out;
- const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
- const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : "";
- action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles);
- }
- }
- else {
- for (const sourceFile of sourceFiles) {
- const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
- const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
- const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
- action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles);
- }
- }
- }
-
- function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
- return options.sourceMap ? jsFilePath + ".map" : undefined;
- }
-
- // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
- // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
- // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
- function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): Extension {
- if (options.jsx === JsxEmit.Preserve) {
- if (isSourceFileJavaScript(sourceFile)) {
- if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) {
- return Extension.Jsx;
- }
- }
- else if (sourceFile.languageVariant === LanguageVariant.JSX) {
- // TypeScript source file preserving JSX syntax
- return Extension.Jsx;
- }
- }
- return Extension.Js;
- }
-
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
let sourceFilePath = getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
const commonSourceDirectory = host.getCommonSourceDirectory();
@@ -4284,6 +4227,16 @@ namespace ts {
return node.kind === SyntaxKind.ParenthesizedExpression;
}
+ export function skipPartiallyEmittedExpressions(node: Expression): Expression;
+ export function skipPartiallyEmittedExpressions(node: Node): Node;
+ export function skipPartiallyEmittedExpressions(node: Node) {
+ while (node.kind === SyntaxKind.PartiallyEmittedExpression) {
+ node = (node).expression;
+ }
+
+ return node;
+ }
+
export function isFunctionExpression(node: Node): node is FunctionExpression {
return node.kind === SyntaxKind.FunctionExpression;
}
diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts
index ff418ab34de94..170a23e34f2e8 100644
--- a/src/harness/compilerRunner.ts
+++ b/src/harness/compilerRunner.ts
@@ -64,6 +64,7 @@ class CompilerBaselineRunner extends RunnerBase {
let result: Harness.Compiler.CompilerResult;
let options: ts.CompilerOptions;
+ let tsConfigFiles: Harness.Compiler.TestFile[];
// equivalent to the files that will be passed on the command line
let toBeCompiled: Harness.Compiler.TestFile[];
// equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files)
@@ -77,10 +78,12 @@ class CompilerBaselineRunner extends RunnerBase {
const units = testCaseContent.testUnitData;
harnessSettings = testCaseContent.settings;
let tsConfigOptions: ts.CompilerOptions;
+ tsConfigFiles = [];
if (testCaseContent.tsConfig) {
assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`);
- tsConfigOptions = ts.clone(testCaseContent.tsConfig.options);
+ tsConfigOptions = ts.cloneCompilerOptions(testCaseContent.tsConfig.options);
+ tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath)));
}
else {
const baseUrl = harnessSettings["baseUrl"];
@@ -98,21 +101,22 @@ class CompilerBaselineRunner extends RunnerBase {
otherFiles = [];
if (testCaseContent.settings["noImplicitReferences"] || /require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) {
- toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions });
+ toBeCompiled.push(this.createHarnessTestFile(lastUnit, rootDir));
units.forEach(unit => {
if (unit.name !== lastUnit.name) {
- otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions });
+ otherFiles.push(this.createHarnessTestFile(unit, rootDir));
}
});
}
else {
toBeCompiled = units.map(unit => {
- return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions };
+ return this.createHarnessTestFile(unit, rootDir);
});
}
if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) {
tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath);
+ tsConfigOptions.configFile.fileName = tsConfigOptions.configFilePath;
}
const output = Harness.Compiler.compileFiles(
@@ -132,11 +136,12 @@ class CompilerBaselineRunner extends RunnerBase {
options = undefined;
toBeCompiled = undefined;
otherFiles = undefined;
+ tsConfigFiles = undefined;
});
// check errors
it("Correct errors for " + fileName, () => {
- Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors);
+ Harness.Compiler.doErrorBaseline(justName, tsConfigFiles.concat(toBeCompiled, otherFiles), result.errors);
});
it (`Correct module resolution tracing for ${fileName}`, () => {
@@ -165,7 +170,7 @@ class CompilerBaselineRunner extends RunnerBase {
it("Correct JS output for " + fileName, () => {
if (hasNonDtsFiles && this.emit) {
- Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, toBeCompiled, otherFiles, harnessSettings);
+ Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, tsConfigFiles, toBeCompiled, otherFiles, harnessSettings);
}
});
@@ -183,6 +188,10 @@ class CompilerBaselineRunner extends RunnerBase {
});
}
+ private createHarnessTestFile(lastUnit: Harness.TestCaseParser.TestUnitData, rootDir: string, unitName?: string): Harness.Compiler.TestFile {
+ return { unitName: unitName || this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions };
+ }
+
public initializeTests() {
describe(this.testSuiteName + " tests", () => {
describe("Setup compiler for compiler baselines", () => {
diff --git a/src/harness/harness.ts b/src/harness/harness.ts
index e944e68f11ea7..d73290f961f3b 100644
--- a/src/harness/harness.ts
+++ b/src/harness/harness.ts
@@ -1125,7 +1125,7 @@ namespace Harness {
compilerOptions: ts.CompilerOptions,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory: string): CompilationOutput {
- const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false };
+ const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.cloneCompilerOptions(compilerOptions) : { noResolve: false };
options.target = options.target || ts.ScriptTarget.ES3;
options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed;
options.noErrorTruncation = true;
@@ -1557,7 +1557,7 @@ namespace Harness {
}
}
- export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
+ export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, tsConfigFiles: Harness.Compiler.TestFile[], toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
}
@@ -1593,7 +1593,7 @@ namespace Harness {
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
jsCode += "\r\n\r\n";
- jsCode += Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
+ jsCode += Harness.Compiler.getErrorBaseline(tsConfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
}
if (jsCode.length > 0) {
@@ -1744,7 +1744,12 @@ namespace Harness {
}
/** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */
- export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; tsConfig: ts.ParsedCommandLine } {
+ export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): {
+ settings: CompilerSettings;
+ testUnitData: TestUnitData[];
+ tsConfig: ts.ParsedCommandLine;
+ tsConfigFileUnitData: TestUnitData;
+ } {
const settings = extractCompilerSettings(code);
// List of all the subfiles we've parsed out
@@ -1830,17 +1835,19 @@ namespace Harness {
// check if project has tsconfig.json in the list of files
let tsConfig: ts.ParsedCommandLine;
+ let tsConfigFileUnitData: TestUnitData;
for (let i = 0; i < testUnitData.length; i++) {
const data = testUnitData[i];
if (ts.getBaseFileName(data.name).toLowerCase() === "tsconfig.json") {
- const configJson = ts.parseConfigFileTextToJson(data.name, data.content);
- assert.isTrue(configJson.config !== undefined);
+ const configJson = ts.parseJsonText(data.name, data.content);
+ assert.isTrue(configJson.endOfFileToken !== undefined);
let baseDir = ts.normalizePath(ts.getDirectoryPath(data.name));
if (rootDir) {
baseDir = ts.getNormalizedAbsolutePath(baseDir, rootDir);
}
- tsConfig = ts.parseJsonConfigFileContent(configJson.config, parseConfigHost, baseDir);
+ tsConfig = ts.parseJsonSourceFileConfigFileContent(configJson, parseConfigHost, baseDir);
tsConfig.options.configFilePath = data.name;
+ tsConfigFileUnitData = data;
// delete entry from the list
ts.orderedRemoveItemAt(testUnitData, i);
@@ -1848,7 +1855,7 @@ namespace Harness {
break;
}
}
- return { settings, testUnitData, tsConfig };
+ return { settings, testUnitData, tsConfig, tsConfigFileUnitData };
}
}
diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts
index 5d4d5a41f3adf..b02164034fa2e 100644
--- a/src/harness/projectsRunner.ts
+++ b/src/harness/projectsRunner.ts
@@ -24,6 +24,7 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera
}
interface CompileProjectFilesResult {
+ configFileSourceFiles: ts.SourceFile[];
moduleKind: ts.ModuleKind;
program?: ts.Program;
compilerOptions?: ts.CompilerOptions;
@@ -124,7 +125,8 @@ class ProjectRunner extends RunnerBase {
return Harness.IO.resolvePath(testCase.projectRoot);
}
- function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: () => string[],
+ function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ts.SourceFile[],
+ getInputFiles: () => string[],
getSourceFileTextImpl: (fileName: string) => string,
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
compilerOptions: ts.CompilerOptions): CompileProjectFilesResult {
@@ -148,6 +150,7 @@ class ProjectRunner extends RunnerBase {
}
return {
+ configFileSourceFiles,
moduleKind,
program,
errors,
@@ -196,6 +199,7 @@ class ProjectRunner extends RunnerBase {
const outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
let inputFiles = testCase.inputFiles;
let compilerOptions = createCompilerOptions();
+ const configFileSourceFiles: ts.SourceFile[] = [];
let configFileName: string;
if (compilerOptions.project) {
@@ -207,41 +211,31 @@ class ProjectRunner extends RunnerBase {
configFileName = ts.findConfigFile("", fileExists);
}
+ let errors: ts.Diagnostic[];
if (configFileName) {
- const result = ts.readConfigFile(configFileName, getSourceFileText);
- if (result.error) {
- return {
- moduleKind,
- errors: [result.error]
- };
- }
-
- const configObject = result.config;
+ const result = ts.readJsonConfigFile(configFileName, getSourceFileText);
+ configFileSourceFiles.push(result);
const configParseHost: ts.ParseConfigHost = {
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
fileExists,
readDirectory,
readFile
};
- const configParseResult = ts.parseJsonConfigFileContent(configObject, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
- if (configParseResult.errors.length > 0) {
- return {
- moduleKind,
- errors: configParseResult.errors
- };
- }
+ const configParseResult = ts.parseJsonSourceFileConfigFileContent(result, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
inputFiles = configParseResult.fileNames;
compilerOptions = configParseResult.options;
+ errors = result.parseDiagnostics.concat(configParseResult.errors);
}
- const projectCompilerResult = compileProjectFiles(moduleKind, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
+ const projectCompilerResult = compileProjectFiles(moduleKind, configFileSourceFiles, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
return {
+ configFileSourceFiles,
moduleKind,
program: projectCompilerResult.program,
compilerOptions,
sourceMapData: projectCompilerResult.sourceMapData,
outputFiles,
- errors: projectCompilerResult.errors,
+ errors: errors ? errors.concat(projectCompilerResult.errors) : projectCompilerResult.errors,
};
function createCompilerOptions() {
@@ -402,7 +396,7 @@ class ProjectRunner extends RunnerBase {
});
// Dont allow config files since we are compiling existing source options
- return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions);
+ return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions);
function findOutputDtsFile(fileName: string) {
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined);
@@ -428,16 +422,16 @@ class ProjectRunner extends RunnerBase {
}
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
- const inputFiles = compilerResult.program ? ts.map(ts.filter(compilerResult.program.getSourceFiles(),
- sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)),
- sourceFile => {
- return {
- unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
- RunnerBase.removeFullPaths(sourceFile.fileName) :
- sourceFile.fileName,
- content: sourceFile.text
- };
- }) : [];
+ const inputFiles = ts.map(compilerResult.configFileSourceFiles.concat(
+ compilerResult.program ?
+ ts.filter(compilerResult.program.getSourceFiles(), sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)) :
+ []),
+ sourceFile => {
+ unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
+ RunnerBase.removeFullPaths(sourceFile.fileName) :
+ sourceFile.fileName,
+ content: sourceFile.text
+ });
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
}
diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts
index 44d2c981c8476..128acb1005d68 100644
--- a/src/harness/rwcRunner.ts
+++ b/src/harness/rwcRunner.ts
@@ -30,6 +30,7 @@ namespace RWC {
describe("Testing a RWC project: " + jsonPath, () => {
let inputFiles: Harness.Compiler.TestFile[] = [];
let otherFiles: Harness.Compiler.TestFile[] = [];
+ let tsconfigFiles: Harness.Compiler.TestFile[] = [];
let compilerResult: Harness.Compiler.CompilerResult;
let compilerOptions: ts.CompilerOptions;
const baselineOpts: Harness.Baseline.BaselineOptions = {
@@ -44,6 +45,7 @@ namespace RWC {
// Therefore we have to clean out large objects after the test is done.
inputFiles = [];
otherFiles = [];
+ tsconfigFiles = [];
compilerResult = undefined;
compilerOptions = undefined;
currentDirectory = undefined;
@@ -74,16 +76,18 @@ namespace RWC {
const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
if (tsconfigFile) {
const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
- const parsedTsconfigFileContents = ts.parseConfigFileTextToJson(tsconfigFile.path, tsconfigFileContents.content);
+ tsconfigFiles.push({ unitName: tsconfigFile.path, content: tsconfigFileContents.content });
+ const parsedTsconfigFileContents = ts.parseJsonText(tsconfigFile.path, tsconfigFileContents.content);
const configParseHost: ts.ParseConfigHost = {
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
fileExists: Harness.IO.fileExists,
readDirectory: Harness.IO.readDirectory,
readFile: Harness.IO.readFile
};
- const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, 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);
+ ts.setConfigFileInOptions(opts.options, configParseResult.options.configFile);
}
// Load the files
@@ -198,8 +202,8 @@ namespace RWC {
return null;
}
// Do not include the library in the baselines to avoid noise
- const baselineFiles = inputFiles.concat(otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
- const errors = compilerResult.errors.filter(e => e.file && !Harness.isDefaultLibraryFile(e.file.fileName));
+ const baselineFiles = tsconfigFiles.concat(inputFiles, otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
+ const errors = compilerResult.errors.filter(e => !e.file || !Harness.isDefaultLibraryFile(e.file.fileName));
return Harness.Compiler.getErrorBaseline(baselineFiles, errors);
}, baselineOpts);
});
@@ -218,7 +222,7 @@ namespace RWC {
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
Harness.IO.newLine() + Harness.IO.newLine() +
- Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
+ Harness.Compiler.getErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
}, baselineOpts);
}
});
@@ -259,4 +263,4 @@ class RWCRunner extends RunnerBase {
private runTest(jsonFileName: string) {
RWC.runRWCTest(jsonFileName);
}
-}
\ No newline at end of file
+}
diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json
index 7366df94ef6d9..eee6473f77f21 100644
--- a/src/harness/tsconfig.json
+++ b/src/harness/tsconfig.json
@@ -24,6 +24,7 @@
"../compiler/checker.ts",
"../compiler/factory.ts",
"../compiler/visitor.ts",
+ "../compiler/transformers/utilities.ts",
"../compiler/transformers/ts.ts",
"../compiler/transformers/jsx.ts",
"../compiler/transformers/esnext.ts",
diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts
index 9bb264b263762..46d9aa462ce3f 100644
--- a/src/harness/unittests/cachingInServerLSHost.ts
+++ b/src/harness/unittests/cachingInServerLSHost.ts
@@ -158,7 +158,7 @@ namespace ts {
// setting compiler options discards module resolution cache
fileExistsCalled = false;
- const compilerOptions = ts.clone(project.getCompilerOptions());
+ const compilerOptions = ts.cloneCompilerOptions(project.getCompilerOptions());
compilerOptions.target = ts.ScriptTarget.ES5;
project.setCompilerOptions(compilerOptions);
diff --git a/src/harness/unittests/configurationExtension.ts b/src/harness/unittests/configurationExtension.ts
index ab5fab2b545d5..2d50d2cb2af97 100644
--- a/src/harness/unittests/configurationExtension.ts
+++ b/src/harness/unittests/configurationExtension.ts
@@ -111,23 +111,47 @@ 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.readJsonConfigFile(entry, name => host.readFile(name));
+ assert(jsonSourceFile.endOfFileToken && !jsonSourceFile.parseDiagnostics.length, flattenDiagnosticMessageText(jsonSourceFile.parseDiagnostics[0] && jsonSourceFile.parseDiagnostics[0].messageText, "\n"));
+ return {
+ jsonSourceFile,
+ parsed: ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry)
+ };
+ }
+
function testSuccess(name: string, entry: string, expected: CompilerOptions, expectedFiles: string[]) {
+ expected.configFilePath = entry;
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"));
+ assert.deepEqual(parsed.options, expected);
+ assert.deepEqual(parsed.fileNames, expectedFiles);
+ });
+
+ it(name + " with jsonSourceFile", () => {
+ const { parsed, jsonSourceFile } = getParseCommandLineJsonSourceFile(entry);
assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n"));
- expected.configFilePath = entry;
assert.deepEqual(parsed.options, expected);
+ assert.equal(parsed.options.configFile, jsonSourceFile);
assert.deepEqual(parsed.fileNames, expectedFiles);
});
}
- function testFailure(name: string, entry: string, expectedDiagnostics: {code: number, category: DiagnosticCategory, messageText: string}[]) {
+ 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 + " with jsonSourceFile", () => {
+ const { parsed } = getParseCommandLineJsonSourceFile(entry);
verifyDiagnostics(parsed.errors, expectedDiagnostics);
});
}
@@ -185,4 +209,4 @@ namespace ts {
});
});
});
-}
\ No newline at end of file
+}
diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts
index 798f8c6a76bb8..4b2fad32d7b55 100644
--- a/src/harness/unittests/convertCompilerOptionsFromJson.ts
+++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts
@@ -4,6 +4,11 @@
namespace ts {
describe("convertCompilerOptionsFromJson", () => {
function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
+ assertCompilerOptionsWithJson(json, configFileName, expectedResult);
+ assertCompilerOptionsWithJsonNode(json, configFileName, expectedResult);
+ }
+
+ function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json["compilerOptions"], "/apath/", configFileName);
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
@@ -21,6 +26,34 @@ namespace ts {
}
}
+ function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
+ const fileText = JSON.stringify(json);
+ 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 } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName);
+ expectedResult.compilerOptions["configFilePath"] = configFileName;
+
+ const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
+ const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions);
+ assert.equal(parsedCompilerOptions, expectedCompilerOptions);
+ assert.equal(actualCompilerOptions.configFile, result);
+
+ 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);
+ const expectedErrors = expectedResult.errors;
+ assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
+ for (let i = 0; i < actualErrors.length; i++) {
+ const actualError = actualErrors[i];
+ const expectedError = expectedErrors[i];
+ assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`);
+ assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`);
+ assert(actualError.file);
+ assert(actualError.start);
+ assert(actualError.length);
+ }
+ }
+
// tsconfig.json tests
it("Convert correctly format tsconfig.json to compiler-options ", () => {
assertCompilerOptions(
diff --git a/src/harness/unittests/convertTypeAcquisitionFromJson.ts b/src/harness/unittests/convertTypeAcquisitionFromJson.ts
index 4c21b7ca2b99d..aae4ee3838212 100644
--- a/src/harness/unittests/convertTypeAcquisitionFromJson.ts
+++ b/src/harness/unittests/convertTypeAcquisitionFromJson.ts
@@ -2,14 +2,20 @@
///
namespace ts {
+ type ExpectedResult = { typeAcquisition: TypeAcquisition, errors: Diagnostic[] };
describe("convertTypeAcquisitionFromJson", () => {
- function assertTypeAcquisition(json: any, configFileName: string, expectedResult: { typeAcquisition: TypeAcquisition, errors: Diagnostic[] }) {
- const jsonOptions = json["typeAcquisition"] || json["typingOptions"];
- const { options: actualTypeAcquisition, errors: actualErrors } = convertTypeAcquisitionFromJson(jsonOptions, "/apath/", configFileName);
+ function assertTypeAcquisition(json: any, configFileName: string, expectedResult: ExpectedResult) {
+ assertTypeAcquisitionWithJson(json, configFileName, expectedResult);
+ assertTypeAcquisitionWithJsonNode(json, configFileName, expectedResult);
+ }
+
+ function verifyAcquisition(actualTypeAcquisition: TypeAcquisition, expectedResult: ExpectedResult) {
const parsedTypeAcquisition = JSON.stringify(actualTypeAcquisition);
const expectedTypeAcquisition = JSON.stringify(expectedResult.typeAcquisition);
assert.equal(parsedTypeAcquisition, expectedTypeAcquisition);
+ }
+ function verifyErrors(actualErrors: Diagnostic[], expectedResult: ExpectedResult, hasLocation?: boolean) {
const expectedErrors = expectedResult.errors;
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
for (let i = 0; i < actualErrors.length; i++) {
@@ -17,9 +23,34 @@ namespace ts {
const expectedError = expectedErrors[i];
assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`);
assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`);
+ if (hasLocation) {
+ assert(actualError.file);
+ assert(actualError.start);
+ assert(actualError.length);
+ }
}
}
+ function assertTypeAcquisitionWithJson(json: any, configFileName: string, expectedResult: ExpectedResult) {
+ const jsonOptions = json["typeAcquisition"] || json["typingOptions"];
+ const { options: actualTypeAcquisition, errors: actualErrors } = convertTypeAcquisitionFromJson(jsonOptions, "/apath/", configFileName);
+ verifyAcquisition(actualTypeAcquisition, expectedResult);
+ verifyErrors(actualErrors, expectedResult);
+ }
+
+ function assertTypeAcquisitionWithJsonNode(json: any, configFileName: string, expectedResult: ExpectedResult) {
+ const fileText = JSON.stringify(json);
+ 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 } = 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);
+ verifyErrors(actualErrors, expectedResult, /*hasLocation*/ true);
+ }
+
// tsconfig.json
it("Convert deprecated typingOptions.enableAutoDiscovery format tsconfig.json to typeAcquisition ", () => {
assertTypeAcquisition(
@@ -177,7 +208,7 @@ namespace ts {
},
errors: [
{
- category: Diagnostics.Unknown_compiler_option_0.category,
+ category: Diagnostics.Unknown_type_acquisition_option_0.category,
code: Diagnostics.Unknown_type_acquisition_option_0.code,
file: undefined,
start: 0,
diff --git a/src/harness/unittests/matchFiles.ts b/src/harness/unittests/matchFiles.ts
index 652379abb3196..e04546719302a 100644
--- a/src/harness/unittests/matchFiles.ts
+++ b/src/harness/unittests/matchFiles.ts
@@ -95,6 +95,44 @@ namespace ts {
assert.deepEqual(actual.errors, expected.errors);
}
+ function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
+ {
+ const jsonText = JSON.stringify(json);
+ 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);
+ }
+ {
+ const actual = ts.parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
+ expected.errors = map(expected.errors, error => {
+ return {
+ category: error.category,
+ code: error.code,
+ file: undefined,
+ length: undefined,
+ messageText: error.messageText,
+ start: undefined,
+ };
+ });
+ assertParsed(actual, expected);
+ }
+ }
+
+ function createDiagnosticForConfigFile(json: any, start: number, length: number, diagnosticMessage: DiagnosticMessage, arg0: string) {
+ const text = JSON.stringify(json);
+ const file = {
+ fileName: caseInsensitiveTsconfigPath,
+ kind: SyntaxKind.SourceFile,
+ text
+ };
+ return ts.createFileDiagnostic(file, start, length, diagnosticMessage, arg0);
+ }
+
describe("matchFiles", () => {
it("with defaults", () => {
const json = {};
@@ -109,8 +147,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
describe("with literal file list", () => {
@@ -130,8 +167,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("missing files are still present", () => {
const json = {
@@ -149,8 +185,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("are not removed due to excludes", () => {
const json = {
@@ -171,8 +206,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
@@ -193,8 +227,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with non .ts file extensions are excluded", () => {
const json = {
@@ -212,8 +245,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("with missing files are excluded", () => {
const json = {
@@ -231,8 +263,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("with literal excludes", () => {
const json = {
@@ -252,8 +283,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with wildcard excludes", () => {
const json = {
@@ -280,8 +310,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with recursive excludes", () => {
const json = {
@@ -307,8 +336,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with case sensitive exclude", () => {
const json = {
@@ -327,8 +355,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
});
it("with common package folders and no exclusions", () => {
const json = {
@@ -352,8 +379,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and exclusions", () => {
const json = {
@@ -379,8 +405,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and empty exclude", () => {
const json = {
@@ -404,8 +429,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
});
@@ -436,8 +460,7 @@ namespace ts {
"c:/dev/x": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("same named declarations are excluded", () => {
@@ -458,8 +481,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("`*` matches only ts files", () => {
const json = {
@@ -479,8 +501,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("`?` matches only a single character", () => {
const json = {
@@ -499,8 +520,7 @@ namespace ts {
"c:/dev/x": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with recursive directory", () => {
const json = {
@@ -521,8 +541,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with multiple recursive directories", () => {
const json = {
@@ -545,8 +564,7 @@ namespace ts {
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("case sensitive", () => {
const json = {
@@ -564,8 +582,7 @@ namespace ts {
"/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
});
it("with missing files are excluded", () => {
const json = {
@@ -584,8 +601,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("always include literal files", () => {
const json = {
@@ -609,8 +625,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude folders", () => {
const json = {
@@ -634,8 +649,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with common package folders and no exclusions", () => {
const json = {
@@ -656,8 +670,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and exclusions", () => {
const json = {
@@ -680,8 +693,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and empty exclude", () => {
const json = {
@@ -703,8 +715,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("exclude .js files when allowJs=false", () => {
const json = {
@@ -728,8 +739,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("include .js files when allowJs=true", () => {
const json = {
@@ -753,8 +763,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include explicitly listed .min.js files when allowJs=true", () => {
const json = {
@@ -778,8 +787,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include paths outside of the project", () => {
const json = {
@@ -802,8 +810,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include paths outside of the project using relative paths", () => {
const json = {
@@ -825,8 +832,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude paths outside of the project using relative paths", () => {
const json = {
@@ -846,8 +852,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("include files with .. in their name", () => {
const json = {
@@ -866,8 +871,7 @@ namespace ts {
],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude files with .. in their name", () => {
const json = {
@@ -888,8 +892,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with jsx=none, allowJs=false", () => {
const json = {
@@ -911,8 +914,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=preserve, allowJs=false", () => {
const json = {
@@ -936,8 +938,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=react-native, allowJs=false", () => {
const json = {
@@ -961,8 +962,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=none, allowJs=true", () => {
const json = {
@@ -986,8 +986,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=preserve, allowJs=true", () => {
const json = {
@@ -1013,8 +1012,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=react-native, allowJs=true", () => {
const json = {
@@ -1040,8 +1038,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("exclude .min.js files using wildcards", () => {
const json = {
@@ -1067,8 +1064,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
describe("with trailing recursive directory", () => {
it("in includes", () => {
@@ -1080,15 +1076,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
+ createDiagnosticForConfigFile(json, 12, 4, ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("in excludes", () => {
const json = {
@@ -1108,8 +1103,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
});
describe("with multiple recursive directory patterns", () => {
@@ -1122,15 +1116,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*"),
+ createDiagnosticForConfigFile(json, 12, 11, ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("in excludes", () => {
const json = {
@@ -1144,7 +1137,7 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**")
+ createDiagnosticForConfigFile(json, 34, 9, ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**")
],
fileNames: [
"c:/dev/a.ts",
@@ -1156,8 +1149,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
@@ -1171,15 +1163,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
+ createDiagnosticForConfigFile(json, 12, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("in includes after a subdirectory", () => {
@@ -1191,15 +1182,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
+ createDiagnosticForConfigFile(json, 12, 11, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
it("in excludes immediately after", () => {
@@ -1214,7 +1204,7 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..")
+ createDiagnosticForConfigFile(json, 34, 7, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..")
],
fileNames: [
"c:/dev/a.ts",
@@ -1226,8 +1216,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in excludes after a subdirectory", () => {
@@ -1242,7 +1231,7 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
- ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
+ createDiagnosticForConfigFile(json, 34, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
],
fileNames: [
"c:/dev/a.ts",
@@ -1254,8 +1243,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
@@ -1272,8 +1260,7 @@ namespace ts {
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
});
@@ -1297,8 +1284,7 @@ namespace ts {
"c:/dev/w": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
});
describe("that are explicitly included", () => {
it("without wildcards", () => {
@@ -1317,8 +1303,7 @@ namespace ts {
],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
});
it("with recursive wildcards that match directories", () => {
const json = {
@@ -1339,8 +1324,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
});
it("with recursive wildcards that match nothing", () => {
const json = {
@@ -1361,8 +1345,7 @@ namespace ts {
"c:/dev/x": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
});
it("with wildcard excludes that implicitly exclude dotted files", () => {
const json = {
@@ -1382,8 +1365,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
- assertParsed(actual, expected);
+ validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
});
});
});
diff --git a/src/harness/unittests/projectErrors.ts b/src/harness/unittests/projectErrors.ts
index 3db3675dbd6b0..30942fb2fdc6f 100644
--- a/src/harness/unittests/projectErrors.ts
+++ b/src/harness/unittests/projectErrors.ts
@@ -6,7 +6,10 @@ namespace ts.projectSystem {
describe("Project errors", () => {
function checkProjectErrors(projectFiles: server.ProjectFilesWithTSDiagnostics, expectedErrors: string[]) {
assert.isTrue(projectFiles !== undefined, "missing project files");
- const errors = projectFiles.projectErrors;
+ checkProjectErrorsWorker(projectFiles.projectErrors, expectedErrors);
+ }
+
+ function checkProjectErrorsWorker(errors: Diagnostic[], expectedErrors: string[]) {
assert.equal(errors ? errors.length : 0, expectedErrors.length, `expected ${expectedErrors.length} error in the list`);
if (expectedErrors.length) {
for (let i = 0; i < errors.length; i++) {
@@ -122,12 +125,13 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
- checkProjectErrors(configuredProject, [
- "')' expected.",
- "Declaration or statement expected.",
- "Declaration or statement expected.",
- "Failed to parse file '/a/b/tsconfig.json'"
+ checkProjectErrors(configuredProject, []);
+ const projectErrors = projectService.configuredProjects[0].getAllProjectErrors();
+ checkProjectErrorsWorker(projectErrors, [
+ "'{' expected."
]);
+ assert.isNotNull(projectErrors[0].file);
+ assert.equal(projectErrors[0].file.fileName, corruptedConfig.path);
}
// fix config and trigger watcher
host.reloadFS([file1, file2, correctConfig]);
@@ -137,6 +141,8 @@ namespace ts.projectSystem {
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
checkProjectErrors(configuredProject, []);
+ const projectErrors = projectService.configuredProjects[0].getAllProjectErrors();
+ checkProjectErrorsWorker(projectErrors, []);
}
});
@@ -166,6 +172,8 @@ namespace ts.projectSystem {
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
checkProjectErrors(configuredProject, []);
+ const projectErrors = projectService.configuredProjects[0].getAllProjectErrors();
+ checkProjectErrorsWorker(projectErrors, []);
}
// break config and trigger watcher
host.reloadFS([file1, file2, corruptedConfig]);
@@ -174,13 +182,14 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
- checkProjectErrors(configuredProject, [
- "')' expected.",
- "Declaration or statement expected.",
- "Declaration or statement expected.",
- "Failed to parse file '/a/b/tsconfig.json'"
+ checkProjectErrors(configuredProject, []);
+ const projectErrors = projectService.configuredProjects[0].getAllProjectErrors();
+ checkProjectErrorsWorker(projectErrors, [
+ "'{' expected."
]);
+ assert.isNotNull(projectErrors[0].file);
+ assert.equal(projectErrors[0].file.fileName, corruptedConfig.path);
}
});
});
-}
\ No newline at end of file
+}
diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts
index 02be254c6f9ca..abc8dd2436049 100644
--- a/src/harness/unittests/telemetry.ts
+++ b/src/harness/unittests/telemetry.ts
@@ -45,7 +45,7 @@ namespace ts.projectSystem {
it("works with external project", () => {
const file1 = makeFile("/a.ts");
const et = new EventTracker([file1]);
- const compilerOptions: ts.CompilerOptions = { strict: true };
+ const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true };
const projectFileName = "/hunter2/foo.csproj";
@@ -138,8 +138,6 @@ namespace ts.projectSystem {
declaration: true,
lib: ["es6", "dom"],
-
- checkJs: "" as any as boolean,
};
(compilerOptions as any).unknownCompilerOption = "hunter2"; // These are always ignored.
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] });
diff --git a/src/harness/unittests/tsconfigParsing.ts b/src/harness/unittests/tsconfigParsing.ts
index 7b980cdd2d8ee..8d56360bba50b 100644
--- a/src/harness/unittests/tsconfigParsing.ts
+++ b/src/harness/unittests/tsconfigParsing.ts
@@ -3,37 +3,69 @@
namespace ts {
describe("parseConfigFileTextToJson", () => {
- function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: Diagnostic }) {
+ function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: Diagnostic[] }) {
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
assert.equal(JSON.stringify(parsed), JSON.stringify(expectedConfigObject));
}
function assertParseError(jsonText: string) {
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
- assert.isTrue(undefined === parsed.config);
+ assert.deepEqual(parsed.config, {});
assert.isTrue(undefined !== parsed.error);
}
function assertParseErrorWithExcludesKeyword(jsonText: string) {
- const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
- const parsedCommand = ts.parseJsonConfigFileContent(parsed.config, 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);
+ {
+ const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
+ const parsedCommand = ts.parseJsonConfigFileContent(parsed.config, 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);
+ }
+ {
+ const parsed = ts.parseJsonText("/apath/tsconfig.json", jsonText);
+ 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);
+ }
}
- function assertParseFileList(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedFileList: string[]) {
- const json = JSON.parse(jsonText);
+ function getParsedCommandJson(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) {
+ const parsed = ts.parseConfigFileTextToJson(configFileName, jsonText);
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
- const parsed = ts.parseJsonConfigFileContent(json, host, basePath, /*existingOptions*/ undefined, configFileName);
- assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort()));
+ return ts.parseJsonConfigFileContent(parsed.config, host, basePath, /*existingOptions*/ undefined, configFileName);
}
- function assertParseFileDiagnostics(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedDiagnosticCode: number) {
- const json = JSON.parse(jsonText);
+ 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);
- const parsed = ts.parseJsonConfigFileContent(json, host, basePath, /*existingOptions*/ undefined, configFileName);
- assert.isTrue(parsed.errors.length >= 0);
- assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)}`);
+ return ts.parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName);
+ }
+
+ function assertParseFileList(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedFileList: string[]) {
+ {
+ const parsed = getParsedCommandJson(jsonText, configFileName, basePath, allFileList);
+ assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort()));
+ }
+ {
+ const parsed = getParsedCommandJsonNode(jsonText, configFileName, basePath, allFileList);
+ assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort()));
+ }
+ }
+
+ function assertParseFileDiagnostics(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedDiagnosticCode: number, noLocation?: boolean) {
+ {
+ const parsed = getParsedCommandJson(jsonText, configFileName, basePath, allFileList);
+ assert.isTrue(parsed.errors.length >= 0);
+ assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)}`);
+ }
+ {
+ const parsed = getParsedCommandJsonNode(jsonText, configFileName, basePath, allFileList);
+ assert.isTrue(parsed.errors.length >= 0);
+ assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)}`);
+ if (!noLocation) {
+ assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode && e.file && e.start && e.length).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)} with location information`);
+ }
+ }
}
it("returns empty config for file with only whitespaces", () => {
@@ -199,7 +231,9 @@ namespace ts {
}
"files": ["file1.ts"]
}`;
- const { configJsonObject, diagnostics } = sanitizeConfigFile("config.json", content);
+ const result = parseJsonText("config.json", content);
+ const diagnostics = result.parseDiagnostics;
+ const configJsonObject = convertToObject(result, diagnostics);
const expectedResult = {
compilerOptions: {
allowJs: true,
@@ -229,7 +263,8 @@ namespace ts {
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.js"],
- Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
+ Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code,
+ /*noLocation*/ true);
});
it("generates errors for empty directory", () => {
@@ -242,7 +277,8 @@ namespace ts {
"/apath/tsconfig.json",
"tests/cases/unittests",
[],
- Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
+ Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code,
+ /*noLocation*/ true);
});
it("generates errors for empty include", () => {
@@ -253,7 +289,8 @@ namespace ts {
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.ts"],
- Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
+ Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code,
+ /*noLocation*/ true);
});
it("generates errors for includes with outDir", () => {
@@ -267,7 +304,8 @@ namespace ts {
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.ts"],
- Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
+ Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code,
+ /*noLocation*/ true);
});
});
}
diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts
index d0ef78ad39dc9..3284c131bae75 100644
--- a/src/harness/unittests/tsserverProjectSystem.ts
+++ b/src/harness/unittests/tsserverProjectSystem.ts
@@ -735,7 +735,7 @@ namespace ts.projectSystem {
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
- checkProjectActualFiles(project, [file1.path, libFile.path, file2.path]);
+ checkProjectActualFiles(project, [file1.path, libFile.path, file2.path, configFile.path]);
checkProjectRootFiles(project, [file1.path, file2.path]);
// watching all files except one that was open
checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]);
@@ -992,7 +992,7 @@ namespace ts.projectSystem {
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
- checkProjectActualFiles(project, [file1.path, nodeModuleFile.path]);
+ checkProjectActualFiles(project, [file1.path, nodeModuleFile.path, configFile.path]);
checkNumberOfInferredProjects(projectService, 1);
configFile.content = `{
@@ -1003,7 +1003,7 @@ namespace ts.projectSystem {
}`;
host.reloadFS(files);
host.triggerFileWatcherCallback(configFile.path);
- checkProjectActualFiles(project, [file1.path, classicModuleFile.path]);
+ checkProjectActualFiles(project, [file1.path, classicModuleFile.path, configFile.path]);
checkNumberOfInferredProjects(projectService, 1);
});
@@ -1566,7 +1566,7 @@ namespace ts.projectSystem {
host.reloadFS([file1, file2, file3, configFile]);
host.triggerDirectoryWatcherCallback(getDirectoryPath(configFile.path), configFile.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, file3.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, file3.path, configFile.path]);
});
it("correctly migrate files between projects", () => {
@@ -1624,7 +1624,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, configFile.path]);
host.reloadFS([file1, file2, configFile]);
@@ -1655,7 +1655,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, configFile.path]);
const modifiedConfigFile = {
path: configFile.path,
@@ -1688,7 +1688,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, configFile.path]);
const modifiedConfigFile = {
path: configFile.path,
@@ -1769,11 +1769,11 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, config.path]);
projectService.openClientFile(file2.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, config.path]);
host.reloadFS([file1, file2]);
host.triggerFileWatcherCallback(config.path, /*removed*/ true);
@@ -1808,13 +1808,13 @@ namespace ts.projectSystem {
});
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, config.path]);
projectService.closeClientFile(f1.path);
projectService.openClientFile(f2.path);
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, config.path]);
checkProjectActualFiles(projectService.inferredProjects[0], [f2.path]);
});
@@ -1838,7 +1838,7 @@ namespace ts.projectSystem {
// HTML file will not be included in any projects yet
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, config.path]);
// Specify .html extension as mixed content
const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }];
@@ -1847,7 +1847,7 @@ namespace ts.projectSystem {
// HTML file still not included in the project as it is closed
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, config.path]);
// Open HTML file
projectService.applyChangesInOpenFiles(
@@ -1857,7 +1857,7 @@ namespace ts.projectSystem {
// Now HTML file is included in the project
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, config.path]);
// Check identifiers defined in HTML content are available in .ts file
const project = projectService.configuredProjects[0];
@@ -1872,7 +1872,7 @@ namespace ts.projectSystem {
// HTML file is still included in project
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [file1.path, file2.path, config.path]);
// Check identifiers defined in HTML content are not available in .ts file
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5);
@@ -2488,7 +2488,7 @@ namespace ts.projectSystem {
options: {}
});
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, tsconfig.path]);
// rename tsconfig.json back to lib.ts
host.reloadFS([f1, f2]);
@@ -2546,8 +2546,8 @@ namespace ts.projectSystem {
options: {}
});
projectService.checkNumberOfProjects({ configuredProjects: 2 });
- checkProjectActualFiles(projectService.configuredProjects[0], [cLib.path]);
- checkProjectActualFiles(projectService.configuredProjects[1], [dLib.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [cLib.path, cTsconfig.path]);
+ checkProjectActualFiles(projectService.configuredProjects[1], [dLib.path, dTsconfig.path]);
// remove one config file
projectService.openExternalProject({
@@ -2557,7 +2557,7 @@ namespace ts.projectSystem {
});
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [dLib.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [dLib.path, dTsconfig.path]);
// remove second config file
projectService.openExternalProject({
@@ -2577,8 +2577,8 @@ namespace ts.projectSystem {
options: {}
});
projectService.checkNumberOfProjects({ configuredProjects: 2 });
- checkProjectActualFiles(projectService.configuredProjects[0], [cLib.path]);
- checkProjectActualFiles(projectService.configuredProjects[1], [dLib.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [cLib.path, cTsconfig.path]);
+ checkProjectActualFiles(projectService.configuredProjects[1], [dLib.path, dTsconfig.path]);
// close all projects - no projects should be opened
projectService.closeExternalProject(projectName);
@@ -2634,13 +2634,13 @@ namespace ts.projectSystem {
projectService.openClientFile(app.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, app.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, app.path, config1.path]);
host.reloadFS([libES5, libES2015Promise, app, config2]);
host.triggerFileWatcherCallback(config1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, libES2015Promise.path, app.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [libES5.path, libES2015Promise.path, app.path, config2.path]);
});
it("should handle non-existing directories in config file", () => {
@@ -2695,7 +2695,7 @@ namespace ts.projectSystem {
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, barTypings.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, barTypings.path, config.path]);
});
});
@@ -2766,7 +2766,7 @@ namespace ts.projectSystem {
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, t1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, t1.path, tsconfig.path]);
// delete t1
host.reloadFS([f1, tsconfig]);
@@ -2775,7 +2775,7 @@ namespace ts.projectSystem {
host.runQueuedTimeoutCallbacks();
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, tsconfig.path]);
// create t2
host.reloadFS([f1, tsconfig, t2]);
@@ -2784,7 +2784,7 @@ namespace ts.projectSystem {
host.runQueuedTimeoutCallbacks();
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, t2.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, t2.path, tsconfig.path]);
});
});
@@ -2969,7 +2969,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, node.path]);
+ checkProjectActualFiles(projectService.configuredProjects[0], [f1.path, node.path, config.path]);
});
});
@@ -3980,4 +3980,69 @@ namespace ts.projectSystem {
assert.isUndefined(project.getCompilerOptions().maxNodeModuleJsDepth);
});
});
+
+ describe("Options Diagnostic locations reported correctly with changes in configFile contents", () => {
+ it("when options change", () => {
+ const file = {
+ path: "/a/b/app.ts",
+ content: "let x = 10"
+ };
+ const configFileContentBeforeComment = `{`;
+ const configFileContentComment = `
+ // comment`;
+ const configFileContentAfterComment = `
+ "compilerOptions": {
+ "allowJs": true,
+ "declaration": true
+ }
+ }`;
+ const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
+ const configFileContentWithoutCommentLine = configFileContentBeforeComment + configFileContentAfterComment;
+
+ const configFile = {
+ path: "/a/b/tsconfig.json",
+ content: configFileContentWithComment
+ };
+ const host = createServerHost([file, libFile, configFile]);
+ const session = createSession(host);
+ openFilesForSession([file], session);
+
+ const projectService = session.getProjectService();
+ checkNumberOfProjects(projectService, { configuredProjects: 1 });
+ const projectName = projectService.configuredProjects[0].getProjectName();
+
+ const diags = session.executeCommand({
+ type: "request",
+ command: server.CommandNames.SemanticDiagnosticsSync,
+ seq: 2,
+ arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
+ }).response;
+ assert.isTrue(diags.length === 2);
+
+ configFile.content = configFileContentWithoutCommentLine;
+ host.reloadFS([file, configFile]);
+ host.triggerFileWatcherCallback(configFile.path);
+
+ const diagsAfterEdit = session.executeCommand({
+ type: "request",
+ command: server.CommandNames.SemanticDiagnosticsSync,
+ seq: 2,
+ arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
+ }).response;
+ assert.isTrue(diagsAfterEdit.length === 2);
+
+ verifyDiagnostic(diags[0], diagsAfterEdit[0]);
+ verifyDiagnostic(diags[1], diagsAfterEdit[1]);
+
+ function verifyDiagnostic(beforeEditDiag: server.protocol.DiagnosticWithLinePosition, afterEditDiag: server.protocol.DiagnosticWithLinePosition) {
+ assert.equal(beforeEditDiag.message, afterEditDiag.message);
+ assert.equal(beforeEditDiag.code, afterEditDiag.code);
+ assert.equal(beforeEditDiag.category, afterEditDiag.category);
+ assert.equal(beforeEditDiag.startLocation.line, afterEditDiag.startLocation.line + 1);
+ assert.equal(beforeEditDiag.startLocation.offset, afterEditDiag.startLocation.offset);
+ assert.equal(beforeEditDiag.endLocation.line, afterEditDiag.endLocation.line + 1);
+ assert.equal(beforeEditDiag.endLocation.offset, afterEditDiag.endLocation.offset);
+ }
+ });
+ });
}
diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts
index c356d0941c02c..6cbef411ebf16 100644
--- a/src/harness/unittests/typingsInstaller.ts
+++ b/src/harness/unittests/typingsInstaller.ts
@@ -80,7 +80,7 @@ namespace ts.projectSystem {
const service = createProjectService(host, { typingsInstaller: installer });
service.openClientFile(f1.path);
service.checkNumberOfProjects({ configuredProjects: 1 });
- checkProjectActualFiles(service.configuredProjects[0], [f1.path, f2.path]);
+ checkProjectActualFiles(service.configuredProjects[0], [f1.path, f2.path, config.path]);
installer.installAll(0);
});
});
@@ -133,12 +133,12 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const p = projectService.configuredProjects[0];
- checkProjectActualFiles(p, [file1.path]);
+ checkProjectActualFiles(p, [file1.path, tsconfig.path]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(p, [file1.path, jquery.path]);
+ checkProjectActualFiles(p, [file1.path, jquery.path, tsconfig.path]);
});
it("inferred project (typings installed)", () => {
@@ -684,12 +684,12 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const p = projectService.configuredProjects[0];
- checkProjectActualFiles(p, [app.path]);
+ checkProjectActualFiles(p, [app.path, jsconfig.path]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
+ checkProjectActualFiles(p, [app.path, jqueryDTS.path, jsconfig.path]);
});
it("configured projects discover from bower_components", () => {
@@ -730,13 +730,13 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const p = projectService.configuredProjects[0];
- checkProjectActualFiles(p, [app.path]);
+ checkProjectActualFiles(p, [app.path, jsconfig.path]);
checkWatchedFiles(host, [jsconfig.path, "/bower_components", "/node_modules"]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
+ checkProjectActualFiles(p, [app.path, jqueryDTS.path, jsconfig.path]);
});
it("configured projects discover from bower.json", () => {
@@ -777,12 +777,12 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const p = projectService.configuredProjects[0];
- checkProjectActualFiles(p, [app.path]);
+ checkProjectActualFiles(p, [app.path, jsconfig.path]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
- checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
+ checkProjectActualFiles(p, [app.path, jqueryDTS.path, jsconfig.path]);
});
it("Malformed package.json should be watched", () => {
@@ -1206,4 +1206,4 @@ namespace ts.projectSystem {
checkProjectActualFiles(projectService.inferredProjects[0], [f1.path]);
});
});
-}
\ No newline at end of file
+}
diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts
index ce7ea4875e5b1..649b5fd5a77e8 100644
--- a/src/server/editorServices.ts
+++ b/src/server/editorServices.ts
@@ -976,20 +976,14 @@ namespace ts.server {
configFilename = normalizePath(configFilename);
const configFileContent = this.host.readFile(configFilename);
- let errors: Diagnostic[];
-
- const result = parseConfigFileTextToJson(configFilename, configFileContent);
- let config = result.config;
- if (result.error) {
- // try to reparse config file
- const { configJsonObject: sanitizedConfig, diagnostics } = sanitizeConfigFile(configFilename, configFileContent);
- config = sanitizedConfig;
- errors = diagnostics.length ? diagnostics : [result.error];
+ const result = parseJsonText(configFilename, configFileContent);
+ if (!result.endOfFileToken) {
+ result.endOfFileToken = { kind: SyntaxKind.EndOfFileToken };
}
-
- const parsedCommandLine = parseJsonConfigFileContent(
- config,
+ const errors = result.parseDiagnostics;
+ const parsedCommandLine = parseJsonSourceFileConfigFileContent(
+ result,
this.host,
getDirectoryPath(configFilename),
/*existingOptions*/ {},
@@ -998,23 +992,23 @@ namespace ts.server {
this.hostConfiguration.extraFileExtensions);
if (parsedCommandLine.errors.length) {
- errors = concatenate(errors, parsedCommandLine.errors);
+ errors.push(...parsedCommandLine.errors);
}
Debug.assert(!!parsedCommandLine.fileNames);
if (parsedCommandLine.fileNames.length === 0) {
- (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename));
+ errors.push(createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename));
return { success: false, configFileErrors: errors };
}
const projectOptions: ProjectOptions = {
files: parsedCommandLine.fileNames,
compilerOptions: parsedCommandLine.options,
- configHasExtendsProperty: config.extends !== undefined,
- configHasFilesProperty: config.files !== undefined,
- configHasIncludeProperty: config.include !== undefined,
- configHasExcludeProperty: config.exclude !== undefined,
+ configHasExtendsProperty: parsedCommandLine.raw["extends"] !== undefined,
+ configHasFilesProperty: parsedCommandLine.raw["files"] !== undefined,
+ configHasIncludeProperty: parsedCommandLine.raw["include"] !== undefined,
+ configHasExcludeProperty: parsedCommandLine.raw["exclude"] !== undefined,
wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories),
typeAcquisition: parsedCommandLine.typeAcquisition,
compileOnSave: parsedCommandLine.compileOnSave
@@ -1183,7 +1177,7 @@ namespace ts.server {
return {
success: conversionResult.success,
project,
- errors: project.getProjectErrors()
+ errors: project.getGlobalProjectErrors()
};
}
diff --git a/src/server/project.ts b/src/server/project.ts
index 0b9df73ccac43..ac040a77ace24 100644
--- a/src/server/project.ts
+++ b/src/server/project.ts
@@ -216,7 +216,14 @@ namespace ts.server {
}
}
- getProjectErrors() {
+ /**
+ * Get the errors that dont have any file name associated
+ */
+ getGlobalProjectErrors() {
+ return filter(this.projectErrors, diagnostic => !diagnostic.file);
+ }
+
+ getAllProjectErrors() {
return this.projectErrors;
}
@@ -363,7 +370,7 @@ namespace ts.server {
return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles);
}
- getFileNames(excludeFilesFromExternalLibraries?: boolean) {
+ getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean) {
if (!this.program) {
return [];
}
@@ -386,9 +393,39 @@ namespace ts.server {
}
result.push(asNormalizedPath(f.fileName));
}
+ if (!excludeConfigFiles) {
+ const configFile = this.program.getCompilerOptions().configFile;
+ if (configFile) {
+ result.push(asNormalizedPath(configFile.fileName));
+ if (configFile.extendedSourceFiles) {
+ for (const f of configFile.extendedSourceFiles) {
+ result.push(asNormalizedPath(f));
+ }
+ }
+ }
+ }
return result;
}
+ hasConfigFile(configFilePath: NormalizedPath) {
+ if (this.program && this.languageServiceEnabled) {
+ const configFile = this.program.getCompilerOptions().configFile;
+ if (configFile) {
+ if (configFilePath === asNormalizedPath(configFile.fileName)) {
+ return true;
+ }
+ if (configFile.extendedSourceFiles) {
+ for (const f of configFile.extendedSourceFiles) {
+ if (configFilePath === asNormalizedPath(f)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
getAllEmittableFiles() {
if (!this.languageServiceEnabled) {
return [];
@@ -663,7 +700,7 @@ namespace ts.server {
if (this.lastReportedFileNames && lastKnownVersion === this.lastReportedVersion) {
// if current structure version is the same - return info without any changes
if (this.projectStructureVersion === this.lastReportedVersion && !updatedFileNames) {
- return { info, projectErrors: this.projectErrors };
+ return { info, projectErrors: this.getGlobalProjectErrors() };
}
// compute and return the difference
const lastReportedFileNames = this.lastReportedFileNames;
@@ -685,14 +722,14 @@ namespace ts.server {
});
this.lastReportedFileNames = currentFiles;
this.lastReportedVersion = this.projectStructureVersion;
- return { info, changes: { added, removed, updated }, projectErrors: this.projectErrors };
+ return { info, changes: { added, removed, updated }, projectErrors: this.getGlobalProjectErrors() };
}
else {
// unknown version - return everything
const projectFileNames = this.getFileNames();
this.lastReportedFileNames = arrayToMap(projectFileNames, x => x);
this.lastReportedVersion = this.projectStructureVersion;
- return { info, files: projectFileNames, projectErrors: this.projectErrors };
+ return { info, files: projectFileNames, projectErrors: this.getGlobalProjectErrors() };
}
}
@@ -782,7 +819,7 @@ namespace ts.server {
setCompilerOptions(options?: CompilerOptions) {
// Avoid manipulating the given options directly
- const newOptions = options ? clone(options) : this.getCompilerOptions();
+ const newOptions = options ? cloneCompilerOptions(options) : this.getCompilerOptions();
if (!newOptions) {
return;
}
diff --git a/src/server/protocol.ts b/src/server/protocol.ts
index f79774abf2058..916d9c51a1440 100644
--- a/src/server/protocol.ts
+++ b/src/server/protocol.ts
@@ -1943,6 +1943,13 @@ namespace ts.server.protocol {
source?: string;
}
+ export interface DiagnosticWithFileName extends Diagnostic {
+ /**
+ * Name of the file the diagnostic is in
+ */
+ fileName: string;
+ }
+
export interface DiagnosticEventBody {
/**
* The file for which diagnostic information is reported.
@@ -1977,7 +1984,7 @@ namespace ts.server.protocol {
/**
* An arry of diagnostic information items for the found config file.
*/
- diagnostics: Diagnostic[];
+ diagnostics: DiagnosticWithFileName[];
}
/**
diff --git a/src/server/session.ts b/src/server/session.ts
index c06e33eb9797f..3f4450e4f4d3e 100644
--- a/src/server/session.ts
+++ b/src/server/session.ts
@@ -84,14 +84,20 @@ namespace ts.server {
};
}
- function formatConfigFileDiag(diag: ts.Diagnostic): protocol.Diagnostic {
- return {
- start: undefined,
- end: undefined,
- text: ts.flattenDiagnosticMessageText(diag.messageText, "\n"),
- category: DiagnosticCategory[diag.category].toLowerCase(),
- source: diag.source
- };
+ function convertToILineInfo(lineAndCharacter: LineAndCharacter): ILineInfo {
+ return { line: lineAndCharacter.line + 1, offset: lineAndCharacter.character + 1 };
+ }
+
+ function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
+ function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: false): protocol.Diagnostic;
+ function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
+ const start = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start));
+ const end = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
+ const text = ts.flattenDiagnosticMessageText(diag.messageText, "\n");
+ const { code, source } = diag;
+ const category = DiagnosticCategory[diag.category].toLowerCase();
+ return includeFileName ? { start, end, text, code, category, source, fileName: diag.file && diag.file.fileName } :
+ { start, end, text, code, category, source };
}
export interface PendingErrorCheck {
@@ -384,7 +390,7 @@ namespace ts.server {
}
public configFileDiagnosticEvent(triggerFile: string, configFile: string, diagnostics: ts.Diagnostic[]) {
- const bakedDiags = ts.map(diagnostics, formatConfigFileDiag);
+ const bakedDiags = ts.map(diagnostics, diagnostic => formatConfigFileDiag(diagnostic, /*includeFileName*/ true));
const ev: protocol.ConfigFileDiagnosticEvent = {
seq: 0,
type: "event",
@@ -517,9 +523,55 @@ namespace ts.server {
return projectFileName && this.projectService.findProject(projectFileName);
}
+ private getConfigFileAndProject(args: protocol.FileRequestArgs) {
+ const project = this.getProject(args.projectFileName);
+ const file = toNormalizedPath(args.file);
+
+ return {
+ configFile: project && project.hasConfigFile(file) && file,
+ project
+ };
+ }
+
+ private getConfigFileDiagnostics(configFile: NormalizedPath, project: Project, includeLinePosition: boolean) {
+ const projectErrors = project.getAllProjectErrors();
+ const optionsErrors = project.getLanguageService().getCompilerOptionsDiagnostics();
+ const diagnosticsForConfigFile = filter(
+ concatenate(projectErrors, optionsErrors),
+ diagnostic => diagnostic.file && diagnostic.file.fileName === configFile
+ );
+ return includeLinePosition ?
+ this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) :
+ map(
+ diagnosticsForConfigFile,
+ diagnostic => formatConfigFileDiag(diagnostic, /*includeFileName*/ false)
+ );
+ }
+
+ private convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics: Diagnostic[]) {
+ return diagnostics.map(d => {
+ message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
+ start: d.start,
+ length: d.length,
+ category: DiagnosticCategory[d.category].toLowerCase(),
+ code: d.code,
+ startLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start)),
+ endLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start + d.length))
+ });
+ }
+
private getCompilerOptionsDiagnostics(args: protocol.CompilerOptionsDiagnosticsRequestArgs) {
const project = this.getProject(args.projectFileName);
- return this.convertToDiagnosticsWithLinePosition(project.getLanguageService().getCompilerOptionsDiagnostics(), /*scriptInfo*/ undefined);
+ // Get diagnostics that dont have associated file with them
+ // The diagnostics which have file would be in config file and
+ // would be reported as part of configFileDiagnostics
+ return this.convertToDiagnosticsWithLinePosition(
+ filter(
+ project.getLanguageService().getCompilerOptionsDiagnostics(),
+ diagnostic => !diagnostic.file
+ ),
+ /*scriptInfo*/ undefined
+ );
}
private convertToDiagnosticsWithLinePosition(diagnostics: Diagnostic[], scriptInfo: ScriptInfo) {
@@ -645,10 +697,20 @@ namespace ts.server {
}
private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
+ const { configFile } = this.getConfigFileAndProject(args);
+ if (configFile) {
+ // all the config file errors are reported as part of semantic check so nothing to report here
+ return [];
+ }
+
return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
}
private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
+ const { configFile, project } = this.getConfigFileAndProject(args);
+ if (configFile) {
+ return this.getConfigFileDiagnostics(configFile, project, args.includeLinePosition);
+ }
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
}
@@ -692,15 +754,15 @@ namespace ts.server {
}
private getProjectInfo(args: protocol.ProjectInfoRequestArgs): protocol.ProjectInfo {
- return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList);
+ return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList, /*excludeConfigFiles*/ false);
}
- private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string, needFileNameList: boolean) {
+ private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string, needFileNameList: boolean, excludeConfigFiles: boolean) {
const { project } = this.getFileAndProjectWorker(uncheckedFileName, projectFileName, /*refreshInferredProjects*/ true, /*errorOnMissingProject*/ true);
const projectInfo = {
configFileName: project.getProjectName(),
languageServiceDisabled: !project.languageServiceEnabled,
- fileNames: needFileNameList ? project.getFileNames() : undefined
+ fileNames: needFileNameList ? project.getFileNames(/*excludeFilesFromExternalLibraries*/ false, excludeConfigFiles) : undefined
};
return projectInfo;
}
@@ -1553,7 +1615,7 @@ namespace ts.server {
}
private getDiagnosticsForProject(next: NextStep, delay: number, fileName: string): void {
- const { fileNames, languageServiceDisabled } = this.getProjectInfoWorker(fileName, /*projectFileName*/ undefined, /*needFileNameList*/ true);
+ const { fileNames, languageServiceDisabled } = this.getProjectInfoWorker(fileName, /*projectFileName*/ undefined, /*needFileNameList*/ true, /*excludeConfigFiles*/ true);
if (languageServiceDisabled) {
return;
}
diff --git a/src/server/utilities.ts b/src/server/utilities.ts
index 9e492601430f8..10290fe864da2 100644
--- a/src/server/utilities.ts
+++ b/src/server/utilities.ts
@@ -49,7 +49,7 @@ namespace ts.server {
export function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings {
return {
projectName: project.getProjectName(),
- fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true),
+ fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true),
compilerOptions: project.getCompilerOptions(),
typeAcquisition,
unresolvedImports,
diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts
index 5e31d6a0190f0..d84ae01e0a071 100644
--- a/src/services/jsTyping.ts
+++ b/src/services/jsTyping.ts
@@ -76,7 +76,7 @@ namespace ts.JsTyping {
if (!safeList) {
const result = readConfigFile(safeListPath, (path: string) => host.readFile(path));
- safeList = result.config ? createMapFromTemplate(result.config) : EmptySafeList;
+ safeList = createMapFromTemplate(result.config);
}
const filesToWatch: string[] = [];
@@ -163,20 +163,18 @@ namespace ts.JsTyping {
filesToWatch.push(jsonPath);
}
const result = readConfigFile(jsonPath, (path: string) => host.readFile(path));
- if (result.config) {
- const jsonConfig: PackageJson = result.config;
- if (jsonConfig.dependencies) {
- mergeTypings(getOwnKeys(jsonConfig.dependencies));
- }
- if (jsonConfig.devDependencies) {
- mergeTypings(getOwnKeys(jsonConfig.devDependencies));
- }
- if (jsonConfig.optionalDependencies) {
- mergeTypings(getOwnKeys(jsonConfig.optionalDependencies));
- }
- if (jsonConfig.peerDependencies) {
- mergeTypings(getOwnKeys(jsonConfig.peerDependencies));
- }
+ const jsonConfig: PackageJson = result.config;
+ if (jsonConfig.dependencies) {
+ mergeTypings(getOwnKeys(jsonConfig.dependencies));
+ }
+ if (jsonConfig.devDependencies) {
+ mergeTypings(getOwnKeys(jsonConfig.devDependencies));
+ }
+ if (jsonConfig.optionalDependencies) {
+ mergeTypings(getOwnKeys(jsonConfig.optionalDependencies));
+ }
+ if (jsonConfig.peerDependencies) {
+ mergeTypings(getOwnKeys(jsonConfig.peerDependencies));
}
}
@@ -222,9 +220,6 @@ namespace ts.JsTyping {
continue;
}
const result = readConfigFile(normalizedFileName, (path: string) => host.readFile(path));
- if (!result.config) {
- continue;
- }
const packageJson: PackageJson = result.config;
// npm 3's package.json contains a "_requiredBy" field
diff --git a/src/services/services.ts b/src/services/services.ts
index 17ad547ed5e7f..b508285b182fb 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -1299,8 +1299,20 @@ namespace ts {
}
}
+ const currentOptions = program.getCompilerOptions();
+ const newOptions = hostCache.compilationSettings();
// If the compilation settings do no match, then the program is not up-to-date
- return compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
+ if (!compareDataObjects(currentOptions, newOptions)) {
+ return false;
+ }
+
+ // If everything matches but the text of config file is changed,
+ // error locations can change for program options, so update the program
+ if (currentOptions.configFile && newOptions.configFile) {
+ return currentOptions.configFile.text === newOptions.configFile.text;
+ }
+
+ return true;
}
}
diff --git a/src/services/shims.ts b/src/services/shims.ts
index 5ad7a5f6161e2..1c37f598021d3 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -1109,27 +1109,16 @@ namespace ts {
() => {
const text = sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength());
- const result = parseConfigFileTextToJson(fileName, text);
-
- if (result.error) {
- return {
- options: {},
- typeAcquisition: {},
- files: [],
- raw: {},
- errors: [realizeDiagnostic(result.error, "\r\n")]
- };
- }
-
+ const result = parseJsonText(fileName, text);
const normalizedFileName = normalizeSlashes(fileName);
- const configFile = parseJsonConfigFileContent(result.config, 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(configFile.errors, "\r\n")
+ errors: realizeDiagnostics(result.parseDiagnostics.concat(configFile.errors), "\r\n")
};
});
}
@@ -1248,4 +1237,4 @@ namespace TypeScript.Services {
// TODO: it should be moved into a namespace though.
/* @internal */
-const toolsVersion = "2.5";
\ No newline at end of file
+const toolsVersion = "2.5";
diff --git a/src/services/transpile.ts b/src/services/transpile.ts
index e10fcc70a6449..561c188c6cdf4 100644
--- a/src/services/transpile.ts
+++ b/src/services/transpile.ts
@@ -130,7 +130,7 @@ namespace ts {
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || filter(optionDeclarations, o =>
typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number"));
- options = clone(options);
+ options = cloneCompilerOptions(options);
for (const opt of commandLineOptionsStringToEnum) {
if (!hasProperty(options, opt.name)) {
diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json
index 0c1d76e7ae5d2..8f8ed11a18835 100644
--- a/src/services/tsconfig.json
+++ b/src/services/tsconfig.json
@@ -17,6 +17,7 @@
"../compiler/checker.ts",
"../compiler/factory.ts",
"../compiler/visitor.ts",
+ "../compiler/transformers/utilities.ts",
"../compiler/transformers/ts.ts",
"../compiler/transformers/jsx.ts",
"../compiler/transformers/esnext.ts",
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index b7717edd86723..78c7140373631 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -982,6 +982,12 @@ namespace ts {
return false;
}
+ export function cloneCompilerOptions(options: CompilerOptions): CompilerOptions {
+ const result = clone(options);
+ setConfigFileInOptions(result, options && options.configFile);
+ return result;
+ }
+
export function compareDataObjects(dst: any, src: any): boolean {
if (!dst || !src || Object.keys(dst).length !== Object.keys(src).length) {
return false;
@@ -1306,30 +1312,6 @@ namespace ts {
return ensureScriptKind(fileName, scriptKind);
}
- export function sanitizeConfigFile(configFileName: string, content: string) {
- const options: TranspileOptions = {
- fileName: "config.js",
- compilerOptions: {
- target: ScriptTarget.ES2015,
- removeComments: true
- },
- reportDiagnostics: true
- };
- const { outputText, diagnostics } = ts.transpileModule("(" + content + ")", options);
- // Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1
- // also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these
- // as well
- const trimmedOutput = outputText.trim();
- for (const diagnostic of diagnostics) {
- diagnostic.start = diagnostic.start - 1;
- }
- const {config, error} = parseConfigFileTextToJson(configFileName, trimmedOutput.substring(1, trimmedOutput.length - 2), /*stripComments*/ false);
- return {
- configJsonObject: config || {},
- diagnostics: error ? concatenate(diagnostics, [error]) : diagnostics
- };
- }
-
export function getFirstNonSpaceCharacterPosition(text: string, position: number) {
while (isWhiteSpaceLike(text.charCodeAt(position))) {
position += 1;
diff --git a/tests/baselines/reference/maxNodeModuleJsDepthDefaultsToZero.errors.txt b/tests/baselines/reference/maxNodeModuleJsDepthDefaultsToZero.errors.txt
index 2218e7910aefd..e9455a4efbd2f 100644
--- a/tests/baselines/reference/maxNodeModuleJsDepthDefaultsToZero.errors.txt
+++ b/tests/baselines/reference/maxNodeModuleJsDepthDefaultsToZero.errors.txt
@@ -1,6 +1,16 @@
/index.ts(4,5): error TS2339: Property 'y' does not exist on type 'typeof "shortid"'.
+==== /tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "outDir": "bin"
+ },
+ "exclude": [ "node_modules" ]
+ }
==== /index.ts (1 errors) ====
///
import * as foo from "shortid";
diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt
index 85e25ec99fb93..8a52830e566d3 100644
--- a/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt
+++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt
@@ -1,7 +1,22 @@
-error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+c:/root/tsconfig.json(5,9): error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+==== c:/root/tsconfig.json (1 errors) ====
+ // paths should error in the absence of baseurl
+
+ {
+ "compilerOptions": {
+ "paths": {
+ ~~~~~~~
!!! error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+ "*": [
+ "*",
+ "generated/*"
+ ]
+ }
+ }
+ }
+
==== c:/root/f1.ts (0 errors) ====
export var x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt
index 85e25ec99fb93..297f4dc85ad53 100644
--- a/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt
+++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt
@@ -1,7 +1,21 @@
-error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+c:/root/tsconfig.json(4,9): error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+==== c:/root/tsconfig.json (1 errors) ====
+ // paths should error in the absence of baseurl
+ {
+ "compilerOptions": {
+ "paths": {
+ ~~~~~~~
!!! error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option.
+ "*": [
+ "*",
+ "generated/*"
+ ]
+ }
+ }
+ }
+
==== c:/root/f1.ts (0 errors) ====
export var x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt
index 3b0a387f64441..3b0261dd39506 100644
--- a/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt
+++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt
@@ -1,8 +1,23 @@
-error TS5061: Pattern '*1*' can have at most one '*' character.
-error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+tests/cases/compiler/root/tsconfig.json(8,13): error TS5061: Pattern '*1*' can have at most one '*' character.
+tests/cases/compiler/root/tsconfig.json(8,22): error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+==== tests/cases/compiler/root/tsconfig.json (2 errors) ====
+ // baseurl is defined in tsconfig.json
+ // paths has errors
+
+ {
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "paths": {
+ "*1*": [ "*2*" ]
+ ~~~~~
!!! error TS5061: Pattern '*1*' can have at most one '*' character.
+ ~~~~~
!!! error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+ }
+ }
+ }
+
==== tests/cases/compiler/root/src/folder1/file1.ts (0 errors) ====
export var x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt
index 3b0a387f64441..3b0261dd39506 100644
--- a/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt
+++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt
@@ -1,8 +1,23 @@
-error TS5061: Pattern '*1*' can have at most one '*' character.
-error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+tests/cases/compiler/root/tsconfig.json(8,13): error TS5061: Pattern '*1*' can have at most one '*' character.
+tests/cases/compiler/root/tsconfig.json(8,22): error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+==== tests/cases/compiler/root/tsconfig.json (2 errors) ====
+ // baseurl is defined in tsconfig.json
+ // paths has errors
+
+ {
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "paths": {
+ "*1*": [ "*2*" ]
+ ~~~~~
!!! error TS5061: Pattern '*1*' can have at most one '*' character.
+ ~~~~~
!!! error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character.
+ }
+ }
+ }
+
==== tests/cases/compiler/root/src/folder1/file1.ts (0 errors) ====
export var x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.errors.txt
index 4b038b99bcc59..0ebe17354493f 100644
--- a/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.errors.txt
+++ b/tests/baselines/reference/pathMappingBasedModuleResolution_withExtension_failedLookup.errors.txt
@@ -1,6 +1,16 @@
/a.ts(1,21): error TS2307: Cannot find module 'foo'.
+==== /tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "foo": ["foo/foo.ts"]
+ }
+ }
+ }
+
==== /a.ts (1 errors) ====
import { foo } from "foo";
~~~~~
diff --git a/tests/baselines/reference/pathsValidation1.errors.txt b/tests/baselines/reference/pathsValidation1.errors.txt
index a2d7be5f355c5..f7330308da153 100644
--- a/tests/baselines/reference/pathsValidation1.errors.txt
+++ b/tests/baselines/reference/pathsValidation1.errors.txt
@@ -1,6 +1,16 @@
-error TS5063: Substitutions for pattern '*' should be an array.
+tests/cases/compiler/tsconfig.json(5,18): error TS5063: Substitutions for pattern '*' should be an array.
+==== tests/cases/compiler/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "*": "*"
+ ~~~
!!! error TS5063: Substitutions for pattern '*' should be an array.
+ }
+ }
+ }
==== tests/cases/compiler/a.ts (0 errors) ====
let x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathsValidation2.errors.txt b/tests/baselines/reference/pathsValidation2.errors.txt
index 8956b2fc15989..c8cf1617a9d8b 100644
--- a/tests/baselines/reference/pathsValidation2.errors.txt
+++ b/tests/baselines/reference/pathsValidation2.errors.txt
@@ -1,6 +1,16 @@
-error TS5064: Substitution '1' for pattern '*' has incorrect type, expected 'string', got 'number'.
+tests/cases/compiler/tsconfig.json(5,19): error TS5064: Substitution '1' for pattern '*' has incorrect type, expected 'string', got 'number'.
+==== tests/cases/compiler/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "*": [1]
+ ~
!!! error TS5064: Substitution '1' for pattern '*' has incorrect type, expected 'string', got 'number'.
+ }
+ }
+ }
==== tests/cases/compiler/a.ts (0 errors) ====
let x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/pathsValidation3.errors.txt b/tests/baselines/reference/pathsValidation3.errors.txt
index 3bb85203e6e38..d701206290b83 100644
--- a/tests/baselines/reference/pathsValidation3.errors.txt
+++ b/tests/baselines/reference/pathsValidation3.errors.txt
@@ -1,6 +1,17 @@
-error TS5066: Substitutions for pattern 'foo' shouldn't be an empty array.
+tests/cases/compiler/tsconfig.json(5,20): error TS5066: Substitutions for pattern 'foo' shouldn't be an empty array.
+==== tests/cases/compiler/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "foo": []
+ ~~
!!! error TS5066: Substitutions for pattern 'foo' shouldn't be an empty array.
+ }
+ }
+ }
+
==== tests/cases/compiler/a.ts (0 errors) ====
let x = 1;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/amd/emitDecoratorMetadataCommonJSISolatedModules.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/amd/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
index d6d803104c96a..f6ad25fddb1d9 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/amd/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/amd/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
@@ -1,6 +1,20 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/node/emitDecoratorMetadataCommonJSISolatedModules.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/node/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
index d6d803104c96a..f6ad25fddb1d9 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/node/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModules/node/emitDecoratorMetadataCommonJSISolatedModules.errors.txt
@@ -1,6 +1,20 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/amd/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/amd/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
index d6d803104c96a..f4fe440f379c5 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/amd/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/amd/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
@@ -1,6 +1,21 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true,
+ "noResolve": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/node/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/node/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
index d6d803104c96a..f4fe440f379c5 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/node/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataCommonJSISolatedModulesNoResolve/node/emitDecoratorMetadataCommonJSISolatedModulesNoResolve.errors.txt
@@ -1,6 +1,21 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true,
+ "noResolve": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/amd/emitDecoratorMetadataSystemJS.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/amd/emitDecoratorMetadataSystemJS.errors.txt
index d6d803104c96a..bd34d2edc4e0e 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/amd/emitDecoratorMetadataSystemJS.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/amd/emitDecoratorMetadataSystemJS.errors.txt
@@ -1,6 +1,19 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/node/emitDecoratorMetadataSystemJS.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/node/emitDecoratorMetadataSystemJS.errors.txt
index d6d803104c96a..bd34d2edc4e0e 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/node/emitDecoratorMetadataSystemJS.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJS/node/emitDecoratorMetadataSystemJS.errors.txt
@@ -1,6 +1,19 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/amd/emitDecoratorMetadataSystemJSISolatedModules.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/amd/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
index d6d803104c96a..b14b090b83964 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/amd/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/amd/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
@@ -1,6 +1,21 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/node/emitDecoratorMetadataSystemJSISolatedModules.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/node/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
index d6d803104c96a..b14b090b83964 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/node/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModules/node/emitDecoratorMetadataSystemJSISolatedModules.errors.txt
@@ -1,6 +1,21 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/amd/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/amd/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
index d6d803104c96a..99fc00df24a34 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/amd/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/amd/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
@@ -1,6 +1,22 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true,
+ "noResolve": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/node/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/node/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
index d6d803104c96a..99fc00df24a34 100644
--- a/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/node/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
+++ b/tests/baselines/reference/project/emitDecoratorMetadataSystemJSISolatedModulesNoResolve/node/emitDecoratorMetadataSystemJSISolatedModulesNoResolve.errors.txt
@@ -1,6 +1,22 @@
main.ts(1,21): error TS2307: Cannot find module 'angular2/core'.
+==== tsconfig.json (0 errors) ====
+ {
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "module": "system",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "isolatedModules": true,
+ "noResolve": true
+ },
+ "files": [
+ "main.ts"
+ ]
+ }
==== main.ts (1 errors) ====
import * as ng from "angular2/core";
~~~~~~~~~~~~~~~
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecified/node/jsFileCompilationDifferentNamesNotSpecified.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecified/node/jsFileCompilationDifferentNamesNotSpecified.errors.txt
index e1a24fa384204..29ab30d47ec49 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecified/node/jsFileCompilationDifferentNamesNotSpecified.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecified/node/jsFileCompilationDifferentNamesNotSpecified.errors.txt
@@ -1,6 +1,11 @@
-error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesNotSpecified/tsconfig.json(2,24): error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+==== DifferentNamesNotSpecified/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "out": "test.js" }
+ ~~~~~
!!! error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+ }
==== DifferentNamesNotSpecified/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
index 67b0592c05f1b..f7028d0655075 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
@@ -1,7 +1,15 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+DifferentNamesNotSpecifiedWithAllowJs/tsconfig.json(4,5): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== DifferentNamesNotSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": {
+ "out": "test.js",
+ "allowJs": true
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ }
+ }
==== DifferentNamesNotSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
==== DifferentNamesNotSpecifiedWithAllowJs/b.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
index dbebea69cceea..6a3c9863cc590 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesNotSpecifiedWithAllowJs.errors.txt
@@ -1,9 +1,18 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesNotSpecifiedWithAllowJs/tsconfig.json(3,5): error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesNotSpecifiedWithAllowJs/tsconfig.json(4,5): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== DifferentNamesNotSpecifiedWithAllowJs/tsconfig.json (2 errors) ====
+ {
+ "compilerOptions": {
+ "out": "test.js",
+ ~~~~~
!!! error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+ "allowJs": true
+ ~~~~~~~~~
+!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ }
+ }
==== DifferentNamesNotSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
==== DifferentNamesNotSpecifiedWithAllowJs/b.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/amd/jsFileCompilationDifferentNamesSpecified.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/amd/jsFileCompilationDifferentNamesSpecified.errors.txt
index 5fa60d18af99d..d737f25497c10 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/amd/jsFileCompilationDifferentNamesSpecified.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/amd/jsFileCompilationDifferentNamesSpecified.errors.txt
@@ -2,5 +2,10 @@ error TS6054: File 'DifferentNamesSpecified/b.js' has unsupported extension. The
!!! error TS6054: File 'DifferentNamesSpecified/b.js' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'.
+==== DifferentNamesSpecified/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": { "out": "test.js" },
+ "files": [ "a.ts", "b.js" ]
+ }
==== DifferentNamesSpecified/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/node/jsFileCompilationDifferentNamesSpecified.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/node/jsFileCompilationDifferentNamesSpecified.errors.txt
index c05a142a93cc0..72b812099dc45 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/node/jsFileCompilationDifferentNamesSpecified.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecified/node/jsFileCompilationDifferentNamesSpecified.errors.txt
@@ -1,8 +1,14 @@
error TS6054: File 'DifferentNamesSpecified/b.js' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'.
-error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesSpecified/tsconfig.json(2,24): error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
!!! error TS6054: File 'DifferentNamesSpecified/b.js' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'.
+==== DifferentNamesSpecified/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "out": "test.js" },
+ ~~~~~
!!! error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+ "files": [ "a.ts", "b.js" ]
+ }
==== DifferentNamesSpecified/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
index 35c913a5835ba..1c5034be858bc 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/amd/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
@@ -1,7 +1,16 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+DifferentNamesSpecifiedWithAllowJs/tsconfig.json(4,5): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== DifferentNamesSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": {
+ "out": "test.js",
+ "allowJs": true
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ },
+ "files": [ "a.ts", "b.js" ]
+ }
==== DifferentNamesSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
==== DifferentNamesSpecifiedWithAllowJs/b.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
index c8c2ca976c61d..c2849fae3a580 100644
--- a/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationDifferentNamesSpecifiedWithAllowJs/node/jsFileCompilationDifferentNamesSpecifiedWithAllowJs.errors.txt
@@ -1,9 +1,19 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesSpecifiedWithAllowJs/tsconfig.json(3,5): error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+DifferentNamesSpecifiedWithAllowJs/tsconfig.json(4,5): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== DifferentNamesSpecifiedWithAllowJs/tsconfig.json (2 errors) ====
+ {
+ "compilerOptions": {
+ "out": "test.js",
+ ~~~~~
!!! error TS6082: Only 'amd' and 'system' modules are supported alongside --out.
+ "allowJs": true
+ ~~~~~~~~~
+!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ },
+ "files": [ "a.ts", "b.js" ]
+ }
==== DifferentNamesSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
==== DifferentNamesSpecifiedWithAllowJs/b.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
index cdec4ffb398f3..1a625b3fe7d6f 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,12 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameDTsSpecifiedWithAllowJs/tsconfig.json(2,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameDTsSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "allowJs": true },
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ "files": [ "a.d.ts" ]
+ }
==== SameNameDTsSpecifiedWithAllowJs/a.d.ts (0 errors) ====
declare var test: number;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/node/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/node/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
index cdec4ffb398f3..1a625b3fe7d6f 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/node/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameDTsSpecifiedWithAllowJs/node/jsFileCompilationSameNameDTsSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,12 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameDTsSpecifiedWithAllowJs/tsconfig.json(2,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameDTsSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "allowJs": true },
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ "files": [ "a.d.ts" ]
+ }
==== SameNameDTsSpecifiedWithAllowJs/a.d.ts (0 errors) ====
declare var test: number;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
index eadcbd8ca994e..aa7418ccc1420 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
@@ -1,11 +1,14 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file.
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
+SameNameDTsNotSpecifiedWithAllowJs/tsconfig.json(1,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
!!! error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file.
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
+==== SameNameDTsNotSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ { "compilerOptions": { "allowJs": true } }
+ ~~~~~~~~~
+!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
==== SameNameDTsNotSpecifiedWithAllowJs/a.d.ts (0 errors) ====
declare var a: number;
==== SameNameDTsNotSpecifiedWithAllowJs/a.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
index eadcbd8ca994e..aa7418ccc1420 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameDtsNotSpecifiedWithAllowJs.errors.txt
@@ -1,11 +1,14 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file.
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
+SameNameDTsNotSpecifiedWithAllowJs/tsconfig.json(1,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
-!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
!!! error TS5055: Cannot write file 'SameNameDTsNotSpecifiedWithAllowJs/a.js' because it would overwrite input file.
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
+==== SameNameDTsNotSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ { "compilerOptions": { "allowJs": true } }
+ ~~~~~~~~~
+!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
==== SameNameDTsNotSpecifiedWithAllowJs/a.d.ts (0 errors) ====
declare var a: number;
==== SameNameDTsNotSpecifiedWithAllowJs/a.js (0 errors) ====
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
index 9eb81a5f9f13d..99e057bb6d05d 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,9 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameFilesNotSpecifiedWithAllowJs/tsconfig.json(1,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameFilesNotSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ { "compilerOptions": { "allowJs": true } }
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
==== SameNameFilesNotSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
index 9eb81a5f9f13d..99e057bb6d05d 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesNotSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,9 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameFilesNotSpecifiedWithAllowJs/tsconfig.json(1,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameFilesNotSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ { "compilerOptions": { "allowJs": true } }
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
==== SameNameFilesNotSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
index ddfb63686b402..f956b6780844e 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/amd/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,12 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameTsSpecifiedWithAllowJs/tsconfig.json(2,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameTsSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "allowJs": true },
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ "files": [ "a.ts" ]
+ }
==== SameNameTsSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt b/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
index ddfb63686b402..f956b6780844e 100644
--- a/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
+++ b/tests/baselines/reference/project/jsFileCompilationSameNameFilesSpecifiedWithAllowJs/node/jsFileCompilationSameNameFilesSpecifiedWithAllowJs.errors.txt
@@ -1,6 +1,12 @@
-error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+SameNameTsSpecifiedWithAllowJs/tsconfig.json(2,24): error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+==== SameNameTsSpecifiedWithAllowJs/tsconfig.json (1 errors) ====
+ {
+ "compilerOptions": { "allowJs": true },
+ ~~~~~~~~~
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
+ "files": [ "a.ts" ]
+ }
==== SameNameTsSpecifiedWithAllowJs/a.ts (0 errors) ====
var test = 10;
\ No newline at end of file
diff --git a/tests/baselines/reference/project/nodeModulesImportHigher/amd/nodeModulesImportHigher.errors.txt b/tests/baselines/reference/project/nodeModulesImportHigher/amd/nodeModulesImportHigher.errors.txt
index 8b4e11eb6065b..6c8b7319c9f28 100644
--- a/tests/baselines/reference/project/nodeModulesImportHigher/amd/nodeModulesImportHigher.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesImportHigher/amd/nodeModulesImportHigher.errors.txt
@@ -1,6 +1,16 @@
importHigher/root.ts(6,1): error TS2322: Type '"10"' is not assignable to type 'number'.
+==== importHigher/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "maxNodeModuleJsDepth": 2
+ }
+ }
+
==== entry.js (0 errors) ====
var m3 = require("m3");
diff --git a/tests/baselines/reference/project/nodeModulesImportHigher/node/nodeModulesImportHigher.errors.txt b/tests/baselines/reference/project/nodeModulesImportHigher/node/nodeModulesImportHigher.errors.txt
index 8b4e11eb6065b..6c8b7319c9f28 100644
--- a/tests/baselines/reference/project/nodeModulesImportHigher/node/nodeModulesImportHigher.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesImportHigher/node/nodeModulesImportHigher.errors.txt
@@ -1,6 +1,16 @@
importHigher/root.ts(6,1): error TS2322: Type '"10"' is not assignable to type 'number'.
+==== importHigher/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "maxNodeModuleJsDepth": 2
+ }
+ }
+
==== entry.js (0 errors) ====
var m3 = require("m3");
diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt
index 5b5199ad7ae8b..a1b170ce6656b 100644
--- a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/amd/nodeModulesMaxDepthExceeded.errors.txt
@@ -2,6 +2,17 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type '"10"' is not assignable to ty
maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it is a constant or a read-only property.
+==== maxDepthExceeded/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file
+ "outDir": "built"
+ },
+ "include": ["**/*"],
+ "exclude": ["node_modules/m2/**/*"]
+ }
+
==== relative.js (0 errors) ====
exports.relativeProp = true;
diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt
index 5b5199ad7ae8b..a1b170ce6656b 100644
--- a/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesMaxDepthExceeded/node/nodeModulesMaxDepthExceeded.errors.txt
@@ -2,6 +2,17 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type '"10"' is not assignable to ty
maxDepthExceeded/root.ts(4,4): error TS2540: Cannot assign to 'rel' because it is a constant or a read-only property.
+==== maxDepthExceeded/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file
+ "outDir": "built"
+ },
+ "include": ["**/*"],
+ "exclude": ["node_modules/m2/**/*"]
+ }
+
==== relative.js (0 errors) ====
exports.relativeProp = true;
diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt
index 684821d60a2fd..a0edfa3a5103d 100644
--- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt
@@ -1,6 +1,14 @@
maxDepthIncreased/root.ts(7,1): error TS2322: Type '"10"' is not assignable to type 'number'.
+==== maxDepthIncreased/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "maxNodeModuleJsDepth": 3
+ }
+ }
+
==== index.js (0 errors) ====
exports.person = {
"name": "John Doe",
diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt
index 684821d60a2fd..a0edfa3a5103d 100644
--- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt
+++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt
@@ -1,6 +1,14 @@
maxDepthIncreased/root.ts(7,1): error TS2322: Type '"10"' is not assignable to type 'number'.
+==== maxDepthIncreased/tsconfig.json (0 errors) ====
+ {
+ "compilerOptions": {
+ "allowJs": true,
+ "maxNodeModuleJsDepth": 3
+ }
+ }
+
==== index.js (0 errors) ====
exports.person = {
"name": "John Doe",
diff --git a/tests/cases/fourslash/server/projectInfo02.ts b/tests/cases/fourslash/server/projectInfo02.ts
index eb86c721ac793..3077deb453c47 100644
--- a/tests/cases/fourslash/server/projectInfo02.ts
+++ b/tests/cases/fourslash/server/projectInfo02.ts
@@ -10,4 +10,4 @@
////{ "files": ["a.ts", "b.ts"] }
goTo.file("a.ts")
-verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts"])
+verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts", "tsconfig.json"])
diff --git a/tests/cases/fourslash/server/projectWithNonExistentFiles.ts b/tests/cases/fourslash/server/projectWithNonExistentFiles.ts
index ceba136bf964e..0e263d9aca6bc 100644
--- a/tests/cases/fourslash/server/projectWithNonExistentFiles.ts
+++ b/tests/cases/fourslash/server/projectWithNonExistentFiles.ts
@@ -10,4 +10,4 @@
////{ "files": ["a.ts", "c.ts", "b.ts"] }
goTo.file("a.ts");
-verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts"])
+verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts", "tsconfig.json"])
diff --git a/tests/cases/unittests/matchFiles.ts b/tests/cases/unittests/matchFiles.ts
index e3448136c082b..5faa9330bcedc 100644
--- a/tests/cases/unittests/matchFiles.ts
+++ b/tests/cases/unittests/matchFiles.ts
@@ -76,6 +76,40 @@ namespace ts {
"c:/dev/jspm_packages/a.ts"
]);
+ function assertParsed(actual: ts.ParsedCommandLine, expected: ts.ParsedCommandLine): void {
+ assert.deepEqual(actual.fileNames, expected.fileNames);
+ assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
+ assert.deepEqual(actual.errors, expected.errors);
+ }
+
+ function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
+ {
+ const jsonText = JSON.stringify(json);
+ const result = parseJsonText("c:/dev/tsconfig.json", 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);
+ }
+ {
+ const actual = ts.parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
+ expected.errors = map(expected.errors, error => {
+ return {
+ category: error.category,
+ code: error.code,
+ file: undefined,
+ length: undefined,
+ messageText: error.messageText,
+ start: undefined,
+ };
+ });
+ assertParsed(actual, expected);
+ }
+ }
+
describe("matchFiles", () => {
describe("with literal file list", () => {
it("without exclusions", () => {
@@ -94,10 +128,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("missing files are still present", () => {
const json = {
@@ -115,10 +146,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("are not removed due to excludes", () => {
const json = {
@@ -139,10 +167,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
@@ -163,10 +188,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with non .ts file extensions are excluded", () => {
const json = {
@@ -181,10 +203,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with missing files are excluded", () => {
const json = {
@@ -199,10 +218,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with literal excludes", () => {
const json = {
@@ -222,10 +238,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with wildcard excludes", () => {
const json = {
@@ -252,10 +265,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with recursive excludes", () => {
const json = {
@@ -281,10 +291,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with case sensitive exclude", () => {
const json = {
@@ -303,10 +310,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
});
it("with common package folders and no exclusions", () => {
const json = {
@@ -327,10 +331,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and exclusions", () => {
const json = {
@@ -356,10 +357,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and empty exclude", () => {
const json = {
@@ -384,10 +382,7 @@ namespace ts {
],
wildcardDirectories: {},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
});
@@ -410,10 +405,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("`*` matches only ts files", () => {
const json = {
@@ -433,10 +425,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("`?` matches only a single character", () => {
const json = {
@@ -455,10 +444,7 @@ namespace ts {
"c:/dev/x": ts.WatchDirectoryFlags.None
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with recursive directory", () => {
const json = {
@@ -479,10 +465,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with multiple recursive directories", () => {
const json = {
@@ -505,10 +488,7 @@ namespace ts {
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("case sensitive", () => {
const json = {
@@ -526,10 +506,7 @@ namespace ts {
"/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
});
it("with missing files are excluded", () => {
const json = {
@@ -545,10 +522,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("always include literal files", () => {
const json = {
@@ -572,10 +546,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude folders", () => {
const json = {
@@ -599,10 +570,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with common package folders and no exclusions", () => {
const json = {
@@ -620,10 +588,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and exclusions", () => {
const json = {
@@ -646,10 +611,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("with common package folders and empty exclude", () => {
const json = {
@@ -671,10 +633,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
});
it("exclude .js files when allowJs=false", () => {
const json = {
@@ -695,10 +654,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include .js files when allowJs=true", () => {
const json = {
@@ -722,10 +678,7 @@ namespace ts {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include paths outside of the project", () => {
const json = {
@@ -748,10 +701,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include paths outside of the project using relative paths", () => {
@@ -774,10 +724,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.None
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude paths outside of the project using relative paths", () => {
const json = {
@@ -794,10 +741,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("include files with .. in their name", () => {
const json = {
@@ -816,10 +760,7 @@ namespace ts {
],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("exclude files with .. in their name", () => {
const json = {
@@ -840,10 +781,7 @@ namespace ts {
"c:/ext": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("with jsx=none, allowJs=false", () => {
@@ -866,10 +804,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=preserve, allowJs=false", () => {
const json = {
@@ -893,10 +828,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=react-native, allowJs=false", () => {
const json = {
@@ -947,10 +879,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=preserve, allowJs=true", () => {
const json = {
@@ -976,10 +905,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
});
it("with jsx=react-native, allowJs=true", () => {
const json = {
@@ -1025,10 +951,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in excludes", () => {
const json = {
@@ -1045,10 +968,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
describe("with multiple recursive directory patterns", () => {
@@ -1066,10 +986,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in excludes", () => {
const json = {
@@ -1095,10 +1012,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
@@ -1117,10 +1031,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in includes after a subdirectory", () => {
@@ -1137,10 +1048,7 @@ namespace ts {
fileNames: [],
wildcardDirectories: {}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in excludes immediately after", () => {
@@ -1167,10 +1075,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
it("in excludes after a subdirectory", () => {
@@ -1197,10 +1102,7 @@ namespace ts {
"c:/dev": ts.WatchDirectoryFlags.Recursive
}
};
- const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
- assert.deepEqual(actual.fileNames, expected.fileNames);
- assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
- assert.deepEqual(actual.errors, expected.errors);
+ validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
});
});
});