@@ -136,10 +136,11 @@ module FourSlash {
136
136
outDir : 'outDir' ,
137
137
sourceMap : 'sourceMap' ,
138
138
sourceRoot : 'sourceRoot' ,
139
+ resolveReference : 'ResolveReference' , // This flag is used to specify entry file for resolve file references. The flag is only allow once per test file
139
140
} ;
140
141
141
142
// List of allowed metadata names
142
- var fileMetadataNames = [ testOptMetadataNames . filename , testOptMetadataNames . emitThisFile ] ;
143
+ var fileMetadataNames = [ testOptMetadataNames . filename , testOptMetadataNames . emitThisFile , testOptMetadataNames . resolveReference ] ;
143
144
var globalMetadataNames = [ testOptMetadataNames . baselineFile , testOptMetadataNames . declaration ,
144
145
testOptMetadataNames . mapRoot , testOptMetadataNames . module , testOptMetadataNames . out ,
145
146
testOptMetadataNames . outDir , testOptMetadataNames . sourceMap , testOptMetadataNames . sourceRoot ]
@@ -236,6 +237,25 @@ module FourSlash {
236
237
throw new Error ( "Operation should be cancelled" ) ;
237
238
}
238
239
240
+ // This function creates IScriptSnapshot object for testing getPreProcessedFileInfo
241
+ // Return object may lack some functionalities for other purposes.
242
+ function createScriptSnapShot ( sourceText : string ) : TypeScript . IScriptSnapshot {
243
+ return {
244
+ getText : ( start : number , end : number ) => {
245
+ return sourceText . substr ( start , end - start ) ;
246
+ } ,
247
+ getLength : ( ) => {
248
+ return sourceText . length ;
249
+ } ,
250
+ getLineStartPositions : ( ) => {
251
+ return < number [ ] > [ ] ;
252
+ } ,
253
+ getChangeRange : ( oldSnapshot : TypeScript . IScriptSnapshot ) => {
254
+ return < TypeScript . TextChangeRange > undefined ;
255
+ }
256
+ } ;
257
+ }
258
+
239
259
export class TestState {
240
260
// Language service instance
241
261
public languageServiceShimHost : Harness . LanguageService . TypeScriptLS ;
@@ -264,6 +284,16 @@ module FourSlash {
264
284
private scenarioActions : string [ ] = [ ] ;
265
285
private taoInvalidReason : string = null ;
266
286
287
+ private inputFiles : ts . Map < string > = { } ; // Map between inputFile's filename and its content for easily looking up when resolving references
288
+
289
+ // Add input file which has matched file name with the given reference-file path.
290
+ // This is necessary when resolveReference flag is specified
291
+ private addMatchedInputFile ( referenceFilePath : string ) {
292
+ var inputFile = this . inputFiles [ referenceFilePath ] ;
293
+ if ( inputFile && ! Harness . isLibraryFile ( referenceFilePath ) ) {
294
+ this . languageServiceShimHost . addScript ( referenceFilePath , inputFile ) ;
295
+ }
296
+ }
267
297
268
298
constructor ( public testData : FourSlashData ) {
269
299
// Initialize the language service with all the scripts
@@ -273,57 +303,57 @@ module FourSlash {
273
303
var compilationSettings = convertGlobalOptionsToCompilationSettings ( this . testData . globalOptions ) ;
274
304
this . languageServiceShimHost . setCompilationSettings ( compilationSettings ) ;
275
305
276
- var inputFiles : { unitName : string ; content : string } [ ] = [ ] ;
306
+ var startResolveFileRef : FourSlashFile = undefined ;
277
307
278
- testData . files . forEach ( file => {
279
- var fixedPath = file . fileName . substr ( file . fileName . indexOf ( 'tests/' ) ) ;
280
- } ) ;
281
-
282
- // NEWTODO: disable resolution for now.
283
- // If the last unit contains require( or /// reference then consider it the only input file
284
- // and the rest will be added via resolution. If not, then assume we have multiple files
285
- // with 0 references in any of them. We could be smarter here to allow scenarios like
286
- // 2 files without references and 1 file with a reference but we have 0 tests like that
287
- // at the moment and an exhaustive search of the test files for that content could be quite slow.
288
- var lastFile = testData . files [ testData . files . length - 1 ] ;
289
- //if (/require\(/.test(lastFile.content) || /reference\spath/.test(lastFile.content)) {
290
- // inputFiles.push({ unitName: lastFile.fileName, content: lastFile.content });
291
- //} else {
292
- inputFiles = testData . files . map ( file => {
293
- return { unitName : file . fileName , content : file . content } ;
308
+ ts . forEach ( testData . files , file => {
309
+ // Create map between fileName and its content for easily looking up when resolveReference flag is specified
310
+ this . inputFiles [ file . fileName ] = file . content ;
311
+ if ( ! startResolveFileRef && file . fileOptions [ testOptMetadataNames . resolveReference ] ) {
312
+ startResolveFileRef = file ;
313
+ } else if ( startResolveFileRef ) {
314
+ // If entry point for resolving file references is already specified, report duplication error
315
+ throw new Error ( "There exists a Fourslash file which has resolveReference flag specified; remove duplicated resolveReference flag" ) ;
316
+ }
294
317
} ) ;
295
- //}
296
-
297
-
298
- // NEWTODO: Re-implement commented-out section
299
- //harnessCompiler.addInputFiles(inputFiles);
300
- //try {
301
- // var resolvedFiles = harnessCompiler.resolve();
302
318
303
- // resolvedFiles.forEach(file => {
304
- // if (!Harness.isLibraryFile(file.path)) {
305
- // var fixedPath = file.path.substr(file.path.indexOf('tests/'));
306
- // var content = harnessCompiler.getContentForFile(fixedPath);
307
- // this.languageServiceShimHost.addScript(fixedPath, content);
308
- // }
309
- // });
319
+ if ( startResolveFileRef ) {
320
+ // Add the entry-point file itself into the languageServiceShimHost
321
+ this . languageServiceShimHost . addScript ( startResolveFileRef . fileName , startResolveFileRef . content ) ;
322
+
323
+ var jsonResolvedResult = JSON . parse ( this . languageServiceShimHost . getCoreService ( ) . getPreProcessedFileInfo ( startResolveFileRef . fileName ,
324
+ createScriptSnapShot ( startResolveFileRef . content ) ) ) ;
325
+ var resolvedResult = jsonResolvedResult . result ;
326
+ var referencedFiles : ts . IFileReference [ ] = resolvedResult . referencedFiles ;
327
+ var importedFiles : ts . IFileReference [ ] = resolvedResult . importedFiles ;
328
+
329
+ // Add triple reference files into language-service host
330
+ ts . forEach ( referencedFiles , referenceFile => {
331
+ // Fourslash insert tests/cases/fourslash into inputFile.unitName so we will properly append the same base directory to refFile path
332
+ var referenceFilePath = "tests/cases/fourslash/" + referenceFile . path ;
333
+ this . addMatchedInputFile ( referenceFilePath ) ;
334
+ } ) ;
310
335
311
- // this.languageServiceShimHost.addScript('lib.d.ts', Harness.Compiler.libTextMinimal);
312
- //}
313
- //finally {
314
- // // harness no longer needs the results of the above work, make sure the next test operations are in a clean state
315
- // harnessCompiler.reset();
316
- //}
336
+ // Add import files into language-service host
337
+ ts . forEach ( importedFiles , importedFile => {
338
+ // Fourslash insert tests/cases/fourslash into inputFile.unitName and import statement doesn't require ".ts"
339
+ // so convert them before making appropriate comparison
340
+ var importedFilePath = "tests/cases/fourslash/" + importedFile . path + ".ts" ;
341
+ this . addMatchedInputFile ( importedFilePath ) ;
342
+ } ) ;
317
343
318
- /// NEWTODO: For now do not resolve, just use the input files
319
- inputFiles . forEach ( file => {
320
- if ( ! Harness . isLibraryFile ( file . unitName ) ) {
321
- this . languageServiceShimHost . addScript ( file . unitName , file . content ) ;
344
+ // Check if no-default-lib flag is false and if so add default library
345
+ if ( ! resolvedResult . isLibFile ) {
346
+ this . languageServiceShimHost . addDefaultLibrary ( ) ;
322
347
}
323
- } ) ;
324
-
325
- this . languageServiceShimHost . addDefaultLibrary ( ) ;
326
-
348
+ } else {
349
+ // resolveReference file-option is not specified then do not resolve any files and include all inputFiles
350
+ ts . forEachKey ( this . inputFiles , fileName => {
351
+ if ( ! Harness . isLibraryFile ( fileName ) ) {
352
+ this . languageServiceShimHost . addScript ( fileName , this . inputFiles [ fileName ] ) ;
353
+ }
354
+ } ) ;
355
+ this . languageServiceShimHost . addDefaultLibrary ( ) ;
356
+ }
327
357
328
358
// Sneak into the language service and get its compiler so we can examine the syntax trees
329
359
this . languageService = this . languageServiceShimHost . getLanguageService ( ) . languageService ;
0 commit comments