Skip to content

Commit 3907cae

Browse files
committed
Merge pull request #2877 from Microsoft/tsconfigSupportInLS
This adds a method to the language service to parse a tsconfig file and correctly calculate the initial collection of files to consider. We expect the 'host' to find the files in the file system.
2 parents f83efcc + 42c1bdd commit 3907cae

8 files changed

+95
-16
lines changed

Diff for: src/compiler/commandLineParser.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,27 @@ module ts {
285285
* Read tsconfig.json file
286286
* @param fileName The path to the config file
287287
*/
288-
export function readConfigFile(fileName: string): any {
288+
export function readConfigFile(fileName: string): { config?: any; error?: Diagnostic } {
289289
try {
290290
var text = sys.readFile(fileName);
291-
return /\S/.test(text) ? JSON.parse(text) : {};
292291
}
293292
catch (e) {
293+
return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
294+
}
295+
return parseConfigFileText(fileName, text);
296+
}
297+
298+
/**
299+
* Parse the text of the tsconfig.json file
300+
* @param fileName The path to the config file
301+
* @param jsonText The text of the config file
302+
*/
303+
export function parseConfigFileText(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
304+
try {
305+
return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} };
306+
}
307+
catch (e) {
308+
return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
294309
}
295310
}
296311

@@ -300,7 +315,7 @@ module ts {
300315
* @param basePath A root directory to resolve relative path entries in the config
301316
* file to. e.g. outDir
302317
*/
303-
export function parseConfigFile(json: any, basePath?: string): ParsedCommandLine {
318+
export function parseConfigFile(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
304319
var errors: Diagnostic[] = [];
305320

306321
return {
@@ -359,7 +374,7 @@ module ts {
359374
}
360375
}
361376
else {
362-
var sysFiles = sys.readDirectory(basePath, ".ts");
377+
var sysFiles = host.readDirectory(basePath, ".ts");
363378
for (var i = 0; i < sysFiles.length; i++) {
364379
var name = sysFiles[i];
365380
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {

Diff for: src/compiler/diagnosticInformationMap.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ module ts {
439439
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
440440
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
441441
Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.Error, key: "Unsupported file encoding." },
442+
Failed_to_parse_file_0_Colon_1: { code: 5014, category: DiagnosticCategory.Error, key: "Failed to parse file '{0}': {1}." },
442443
Unknown_compiler_option_0: { code: 5023, category: DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
443444
Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
444445
Could_not_write_file_0_Colon_1: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },

Diff for: src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,10 @@
17441744
"category": "Error",
17451745
"code": 5013
17461746
},
1747+
"Failed to parse file '{0}': {1}.": {
1748+
"category": "Error",
1749+
"code": 5014
1750+
},
17471751
"Unknown compiler option '{0}'.": {
17481752
"category": "Error",
17491753
"code": 5023

Diff for: src/compiler/tsc.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,15 @@ module ts {
208208

209209
if (!cachedProgram) {
210210
if (configFileName) {
211-
var configObject = readConfigFile(configFileName);
212-
if (!configObject) {
213-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, configFileName));
211+
212+
let result = readConfigFile(configFileName);
213+
if (result.error) {
214+
reportDiagnostic(result.error);
214215
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
215216
}
216-
var configParseResult = parseConfigFile(configObject, getDirectoryPath(configFileName));
217+
218+
let configObject = result.config;
219+
let configParseResult = parseConfigFile(configObject, sys, getDirectoryPath(configFileName));
217220
if (configParseResult.errors.length > 0) {
218221
reportDiagnostics(configParseResult.errors);
219222
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
@@ -230,7 +233,7 @@ module ts {
230233
compilerHost.getSourceFile = getSourceFile;
231234
}
232235

233-
var compileResult = compile(rootFileNames, compilerOptions, compilerHost);
236+
let compileResult = compile(rootFileNames, compilerOptions, compilerHost);
234237

235238
if (!compilerOptions.watch) {
236239
return sys.exit(compileResult.exitStatus);

Diff for: src/compiler/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,10 @@ module ts {
10321032
getCurrentDirectory(): string;
10331033
}
10341034

1035+
export interface ParseConfigHost {
1036+
readDirectory(rootDir: string, extension: string): string[];
1037+
}
1038+
10351039
export interface WriteFileCallback {
10361040
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
10371041
}

Diff for: src/harness/harnessLanguageService.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ module Harness.LanguageService {
186186
var script = this.getScriptInfo(fileName);
187187
return script ? script.version.toString() : undefined;
188188
}
189+
189190
log(s: string): void { }
190191
trace(s: string): void { }
191192
error(s: string): void { }
@@ -203,7 +204,7 @@ module Harness.LanguageService {
203204
}
204205

205206
/// Shim adapter
206-
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost {
207+
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost {
207208
private nativeHost: NativeLanguageServiceHost;
208209
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
209210
super(cancellationToken, options);
@@ -227,6 +228,11 @@ module Harness.LanguageService {
227228
}
228229
getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); }
229230
getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); }
231+
232+
readDirectory(rootDir: string, extension: string): string {
233+
throw new Error("NYI");
234+
}
235+
230236
log(s: string): void { this.nativeHost.log(s); }
231237
trace(s: string): void { this.nativeHost.trace(s); }
232238
error(s: string): void { this.nativeHost.error(s); }

Diff for: src/server/editorServices.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ module ts.server {
910910
return { errorMsg: "tsconfig syntax error" };
911911
}
912912
else {
913-
var parsedCommandLine = ts.parseConfigFile(rawConfig, dirPath);
913+
var parsedCommandLine = ts.parseConfigFile(rawConfig, ts.sys, dirPath);
914914
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
915915
return { errorMsg: "tsconfig option errors" };
916916
}

Diff for: src/services/shims.ts

+51-5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ module ts {
5757
getNewLine?(): string;
5858
}
5959

60+
/** Public interface of the the of a config service shim instance.*/
61+
export interface CoreServicesShimHost extends Logger {
62+
/** Returns a JSON-encoded value of the type: string[] */
63+
readDirectory(rootDir: string, extension: string): string;
64+
}
65+
6066
///
6167
/// Pre-processing
6268
///
@@ -77,7 +83,7 @@ module ts {
7783
export interface Shim {
7884
dispose(dummy: any): void;
7985
}
80-
86+
8187
export interface LanguageServiceShim extends Shim {
8288
languageService: LanguageService;
8389

@@ -188,6 +194,7 @@ module ts {
188194

189195
export interface CoreServicesShim extends Shim {
190196
getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
197+
getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
191198
getDefaultCompilationSettings(): string;
192199
}
193200

@@ -302,6 +309,17 @@ module ts {
302309
}
303310
}
304311
}
312+
313+
export class CoreServicesShimHostAdapter implements ParseConfigHost {
314+
315+
constructor(private shimHost: CoreServicesShimHost) {
316+
}
317+
318+
public readDirectory(rootDir: string, extension: string): string[] {
319+
var encoded = this.shimHost.readDirectory(rootDir, extension);
320+
return JSON.parse(encoded);
321+
}
322+
}
305323

306324
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any): any {
307325
logger.log(actionDescription);
@@ -741,7 +759,8 @@ module ts {
741759
}
742760

743761
class CoreServicesShimObject extends ShimBase implements CoreServicesShim {
744-
constructor(factory: ShimFactory, public logger: Logger) {
762+
763+
constructor(factory: ShimFactory, public logger: Logger, private host: CoreServicesShimHostAdapter) {
745764
super(factory);
746765
}
747766

@@ -779,6 +798,32 @@ module ts {
779798
});
780799
}
781800

801+
public getTSConfigFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
802+
return this.forwardJSONCall(
803+
"getTSConfigFileInfo('" + fileName + "')",
804+
() => {
805+
let text = sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength());
806+
807+
let result = parseConfigFileText(fileName, text);
808+
809+
if (result.error) {
810+
return {
811+
options: {},
812+
files: [],
813+
errors: [realizeDiagnostic(result.error, '\r\n')]
814+
};
815+
}
816+
817+
var configFile = parseConfigFile(result.config, this.host, getDirectoryPath(normalizeSlashes(fileName)));
818+
819+
return {
820+
options: configFile.options,
821+
files: configFile.fileNames,
822+
errors: realizeDiagnostics(configFile.errors, '\r\n')
823+
};
824+
});
825+
}
826+
782827
public getDefaultCompilationSettings(): string {
783828
return this.forwardJSONCall(
784829
"getDefaultCompilationSettings()",
@@ -821,12 +866,13 @@ module ts {
821866
}
822867
}
823868

824-
public createCoreServicesShim(logger: Logger): CoreServicesShim {
869+
public createCoreServicesShim(host: CoreServicesShimHost): CoreServicesShim {
825870
try {
826-
return new CoreServicesShimObject(this, logger);
871+
var adapter = new CoreServicesShimHostAdapter(host);
872+
return new CoreServicesShimObject(this, <Logger>host, adapter);
827873
}
828874
catch (err) {
829-
logInternalError(logger, err);
875+
logInternalError(<Logger>host, err);
830876
throw err;
831877
}
832878
}

0 commit comments

Comments
 (0)