Skip to content

Commit 3dbfecd

Browse files
committed
Report option diagnostic in tsconfig.json if possible
1 parent 0dd944a commit 3dbfecd

File tree

53 files changed

+640
-102
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+640
-102
lines changed

src/compiler/commandLineParser.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ namespace ts {
10351035
case "project":
10361036
break;
10371037
default:
1038-
const value = options[name];
1038+
const value = <CompilerOptionsValue>options[name];
10391039
let optionDefinition = optionsNameMap[name.toLowerCase()];
10401040
if (optionDefinition) {
10411041
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
@@ -1201,6 +1201,7 @@ namespace ts {
12011201

12021202
options = extend(existingOptions, options);
12031203
options.configFilePath = configFileName;
1204+
options.configFile = sourceFile;
12041205

12051206
const { fileNames, wildcardDirectories } = getFileNames(errors);
12061207

@@ -1646,17 +1647,15 @@ namespace ts {
16461647

16471648
function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
16481649
if (jsonSourceFile && jsonSourceFile.jsonObject) {
1649-
for (const property of jsonSourceFile.jsonObject.properties) {
1650-
if (property.kind === SyntaxKind.PropertyAssignment && getTextOfPropertyName(property.name) === specKey) {
1651-
const specsNode = <ArrayLiteralExpression>property.initializer;
1652-
for (const element of specsNode.elements) {
1650+
for (const property of getPropertyAssignment(jsonSourceFile.jsonObject, specKey)) {
1651+
if (isArrayLiteralExpression(property.initializer)) {
1652+
for (const element of property.initializer.elements) {
16531653
if (element.kind === SyntaxKind.StringLiteral && (<StringLiteral>element).text === spec) {
16541654
return createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec);
16551655
}
16561656
}
16571657
}
16581658
}
1659-
16601659
}
16611660
return createCompilerDiagnostic(message, spec);
16621661
}

src/compiler/program.ts

+119-29
Large diffs are not rendered by default.

src/compiler/types.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3138,6 +3138,7 @@ namespace ts {
31383138
baseUrl?: string;
31393139
charset?: string;
31403140
/* @internal */ configFilePath?: string;
3141+
/* @internal */ configFile?: JsonSourceFile;
31413142
declaration?: boolean;
31423143
declarationDir?: string;
31433144
/* @internal */ diagnostics?: boolean;
@@ -3206,7 +3207,7 @@ namespace ts {
32063207
/*@internal*/ version?: boolean;
32073208
/*@internal*/ watch?: boolean;
32083209

3209-
[option: string]: CompilerOptionsValue | undefined;
3210+
[option: string]: CompilerOptionsValue | JsonSourceFile | undefined;
32103211
}
32113212

32123213
export interface TypeAcquisition {

src/compiler/utilities.ts

+9
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,15 @@ namespace ts {
901901
return predicate && predicate.kind === TypePredicateKind.This;
902902
}
903903

904+
export function getPropertyAssignment(objectLiteral: ObjectLiteralExpression, key: string, key2?: string) {
905+
return <PropertyAssignment[]>filter(objectLiteral.properties, property => {
906+
if (property.kind === SyntaxKind.PropertyAssignment) {
907+
const propName = getTextOfPropertyName(property.name);
908+
return key === propName || (key2 && key2 === propName);
909+
}
910+
});
911+
}
912+
904913
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
905914
while (true) {
906915
node = node.parent;

src/harness/compilerRunner.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class CompilerBaselineRunner extends RunnerBase {
6464

6565
let result: Harness.Compiler.CompilerResult;
6666
let options: ts.CompilerOptions;
67+
let tsConfigFiles: Harness.Compiler.TestFile[];
6768
// equivalent to the files that will be passed on the command line
6869
let toBeCompiled: Harness.Compiler.TestFile[];
6970
// 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 {
7778
const units = testCaseContent.testUnitData;
7879
harnessSettings = testCaseContent.settings;
7980
let tsConfigOptions: ts.CompilerOptions;
81+
tsConfigFiles = [];
8082
if (testCaseContent.tsConfig) {
8183
assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`);
8284

8385
tsConfigOptions = ts.clone(testCaseContent.tsConfig.options);
86+
tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath)));
8487
}
8588
else {
8689
const baseUrl = harnessSettings["baseUrl"];
@@ -98,21 +101,22 @@ class CompilerBaselineRunner extends RunnerBase {
98101
otherFiles = [];
99102

100103
if (testCaseContent.settings["noImplicitReferences"] || /require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) {
101-
toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions });
104+
toBeCompiled.push(this.createHarnessTestFile(lastUnit, rootDir));
102105
units.forEach(unit => {
103106
if (unit.name !== lastUnit.name) {
104-
otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions });
107+
otherFiles.push(this.createHarnessTestFile(unit, rootDir));
105108
}
106109
});
107110
}
108111
else {
109112
toBeCompiled = units.map(unit => {
110-
return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content, fileOptions: unit.fileOptions };
113+
return this.createHarnessTestFile(unit, rootDir);
111114
});
112115
}
113116

114117
if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) {
115118
tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath);
119+
tsConfigOptions.configFile.fileName = tsConfigOptions.configFilePath;
116120
}
117121

118122
const output = Harness.Compiler.compileFiles(
@@ -132,11 +136,12 @@ class CompilerBaselineRunner extends RunnerBase {
132136
options = undefined;
133137
toBeCompiled = undefined;
134138
otherFiles = undefined;
139+
tsConfigFiles = undefined;
135140
});
136141

137142
// check errors
138143
it("Correct errors for " + fileName, () => {
139-
Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors);
144+
Harness.Compiler.doErrorBaseline(justName, tsConfigFiles.concat(toBeCompiled, otherFiles), result.errors);
140145
});
141146

142147
it (`Correct module resolution tracing for ${fileName}`, () => {
@@ -165,7 +170,7 @@ class CompilerBaselineRunner extends RunnerBase {
165170

166171
it("Correct JS output for " + fileName, () => {
167172
if (hasNonDtsFiles && this.emit) {
168-
Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, toBeCompiled, otherFiles, harnessSettings);
173+
Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, tsConfigFiles, toBeCompiled, otherFiles, harnessSettings);
169174
}
170175
});
171176

@@ -183,6 +188,10 @@ class CompilerBaselineRunner extends RunnerBase {
183188
});
184189
}
185190

191+
private createHarnessTestFile(lastUnit: Harness.TestCaseParser.TestUnitData, rootDir: string, unitName?: string): Harness.Compiler.TestFile {
192+
return { unitName: unitName || this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions };
193+
}
194+
186195
public initializeTests() {
187196
describe(this.testSuiteName + " tests", () => {
188197
describe("Setup compiler for compiler baselines", () => {

src/harness/harness.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,7 @@ namespace Harness {
16001600
}
16011601
}
16021602

1603-
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
1603+
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) {
16041604
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
16051605
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
16061606
}
@@ -1636,7 +1636,7 @@ namespace Harness {
16361636
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
16371637
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
16381638
jsCode += "\r\n\r\n";
1639-
jsCode += Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
1639+
jsCode += Harness.Compiler.getErrorBaseline(tsConfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
16401640
}
16411641

16421642
if (jsCode.length > 0) {
@@ -1787,7 +1787,12 @@ namespace Harness {
17871787
}
17881788

17891789
/** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */
1790-
export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; tsConfig: ts.ParsedCommandLine } {
1790+
export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): {
1791+
settings: CompilerSettings;
1792+
testUnitData: TestUnitData[];
1793+
tsConfig: ts.ParsedCommandLine;
1794+
tsConfigFileUnitData: TestUnitData;
1795+
} {
17911796
const settings = extractCompilerSettings(code);
17921797

17931798
// List of all the subfiles we've parsed out
@@ -1873,6 +1878,7 @@ namespace Harness {
18731878

18741879
// check if project has tsconfig.json in the list of files
18751880
let tsConfig: ts.ParsedCommandLine;
1881+
let tsConfigFileUnitData: TestUnitData;
18761882
for (let i = 0; i < testUnitData.length; i++) {
18771883
const data = testUnitData[i];
18781884
if (ts.getBaseFileName(data.name).toLowerCase() === "tsconfig.json") {
@@ -1884,14 +1890,15 @@ namespace Harness {
18841890
}
18851891
tsConfig = ts.parseJsonSourceFileConfigFileContent(configJson, parseConfigHost, baseDir);
18861892
tsConfig.options.configFilePath = data.name;
1893+
tsConfigFileUnitData = data;
18871894

18881895
// delete entry from the list
18891896
ts.orderedRemoveItemAt(testUnitData, i);
18901897

18911898
break;
18921899
}
18931900
}
1894-
return { settings, testUnitData, tsConfig };
1901+
return { settings, testUnitData, tsConfig, tsConfigFileUnitData };
18951902
}
18961903
}
18971904

src/harness/projectsRunner.ts

+20-13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera
2424
}
2525

2626
interface CompileProjectFilesResult {
27+
configFileSourceFiles: ts.SourceFile[];
2728
moduleKind: ts.ModuleKind;
2829
program?: ts.Program;
2930
compilerOptions?: ts.CompilerOptions;
@@ -125,7 +126,8 @@ class ProjectRunner extends RunnerBase {
125126
return Harness.IO.resolvePath(testCase.projectRoot);
126127
}
127128

128-
function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: () => string[],
129+
function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ts.SourceFile[],
130+
getInputFiles: () => string[],
129131
getSourceFileTextImpl: (fileName: string) => string,
130132
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
131133
compilerOptions: ts.CompilerOptions): CompileProjectFilesResult {
@@ -149,6 +151,7 @@ class ProjectRunner extends RunnerBase {
149151
}
150152

151153
return {
154+
configFileSourceFiles,
152155
moduleKind,
153156
program,
154157
errors,
@@ -197,6 +200,7 @@ class ProjectRunner extends RunnerBase {
197200
const outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
198201
let inputFiles = testCase.inputFiles;
199202
let compilerOptions = createCompilerOptions();
203+
const configFileSourceFiles: ts.SourceFile[] = [];
200204

201205
let configFileName: string;
202206
if (compilerOptions.project) {
@@ -211,6 +215,7 @@ class ProjectRunner extends RunnerBase {
211215
let errors: ts.Diagnostic[];
212216
if (configFileName) {
213217
const result = ts.readConfigFileToJsonSourceFile(configFileName, getSourceFileText);
218+
configFileSourceFiles.push(result);
214219
const configParseHost: ts.ParseConfigHost = {
215220
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
216221
fileExists,
@@ -220,6 +225,7 @@ class ProjectRunner extends RunnerBase {
220225
const configParseResult = ts.parseJsonSourceFileConfigFileContent(result, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
221226
if (configParseResult.errors.length > 0) {
222227
return {
228+
configFileSourceFiles,
223229
moduleKind,
224230
errors: result.parseDiagnostics.concat(configParseResult.errors)
225231
};
@@ -229,8 +235,9 @@ class ProjectRunner extends RunnerBase {
229235
errors = result.parseDiagnostics;
230236
}
231237

232-
const projectCompilerResult = compileProjectFiles(moduleKind, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
238+
const projectCompilerResult = compileProjectFiles(moduleKind, configFileSourceFiles, () => inputFiles, getSourceFileText, writeFile, compilerOptions);
233239
return {
240+
configFileSourceFiles,
234241
moduleKind,
235242
program: projectCompilerResult.program,
236243
compilerOptions,
@@ -394,7 +401,7 @@ class ProjectRunner extends RunnerBase {
394401
});
395402

396403
// Dont allow config files since we are compiling existing source options
397-
return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions);
404+
return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions);
398405

399406
function findOutputDtsFile(fileName: string) {
400407
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined);
@@ -420,16 +427,16 @@ class ProjectRunner extends RunnerBase {
420427
}
421428

422429
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
423-
const inputFiles = compilerResult.program ? ts.map(ts.filter(compilerResult.program.getSourceFiles(),
424-
sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)),
425-
sourceFile => {
426-
return {
427-
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
428-
RunnerBase.removeFullPaths(sourceFile.fileName) :
429-
sourceFile.fileName,
430-
content: sourceFile.text
431-
};
432-
}) : [];
430+
const inputFiles = ts.map(compilerResult.configFileSourceFiles.concat(
431+
compilerResult.program ?
432+
ts.filter(compilerResult.program.getSourceFiles(), sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)) :
433+
[]),
434+
sourceFile => <Harness.Compiler.TestFile>{
435+
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
436+
RunnerBase.removeFullPaths(sourceFile.fileName) :
437+
sourceFile.fileName,
438+
content: sourceFile.text
439+
});
433440

434441
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
435442
}

src/harness/rwcRunner.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace RWC {
3030
describe("Testing a RWC project: " + jsonPath, () => {
3131
let inputFiles: Harness.Compiler.TestFile[] = [];
3232
let otherFiles: Harness.Compiler.TestFile[] = [];
33+
let tsconfigFiles: Harness.Compiler.TestFile[] = [];
3334
let compilerResult: Harness.Compiler.CompilerResult;
3435
let compilerOptions: ts.CompilerOptions;
3536
const baselineOpts: Harness.Baseline.BaselineOptions = {
@@ -44,6 +45,7 @@ namespace RWC {
4445
// Therefore we have to clean out large objects after the test is done.
4546
inputFiles = [];
4647
otherFiles = [];
48+
tsconfigFiles = [];
4749
compilerResult = undefined;
4850
compilerOptions = undefined;
4951
currentDirectory = undefined;
@@ -74,6 +76,7 @@ namespace RWC {
7476
const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
7577
if (tsconfigFile) {
7678
const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
79+
tsconfigFiles.push({ unitName: tsconfigFile.path, content: tsconfigFileContents.content });
7780
const parsedTsconfigFileContents = ts.parseJsonText(tsconfigFile.path, tsconfigFileContents.content);
7881
const configParseHost: ts.ParseConfigHost = {
7982
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
@@ -198,8 +201,8 @@ namespace RWC {
198201
return null;
199202
}
200203
// Do not include the library in the baselines to avoid noise
201-
const baselineFiles = inputFiles.concat(otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
202-
const errors = compilerResult.errors.filter(e => e.file && !Harness.isDefaultLibraryFile(e.file.fileName));
204+
const baselineFiles = tsconfigFiles.concat(inputFiles, otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
205+
const errors = compilerResult.errors.filter(e => !e.file || !Harness.isDefaultLibraryFile(e.file.fileName));
203206
return Harness.Compiler.getErrorBaseline(baselineFiles, errors);
204207
}, baselineOpts);
205208
});
@@ -218,7 +221,7 @@ namespace RWC {
218221

219222
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
220223
Harness.IO.newLine() + Harness.IO.newLine() +
221-
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
224+
Harness.Compiler.getErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
222225
}, baselineOpts);
223226
}
224227
});

0 commit comments

Comments
 (0)