@@ -399,14 +399,31 @@ namespace ts {
399
399
}
400
400
}
401
401
402
- export function createSourceFile ( fileName : string , sourceText : string , languageVersion : ScriptTarget , setParentNodes = false ) : SourceFile {
402
+ export function createSourceFile ( fileName : string , sourceText : string , languageVersion : ScriptTarget , setParentNodes = false , scriptKind ?: ScriptKind ) : SourceFile {
403
403
const start = new Date ( ) . getTime ( ) ;
404
- const result = Parser . parseSourceFile ( fileName , sourceText , languageVersion , /*syntaxCursor*/ undefined , setParentNodes ) ;
404
+ const result = Parser . parseSourceFile ( fileName , sourceText , languageVersion , /*syntaxCursor*/ undefined , setParentNodes , scriptKind ) ;
405
405
406
406
parseTime += new Date ( ) . getTime ( ) - start ;
407
407
return result ;
408
408
}
409
409
410
+ /* @internal */
411
+ export function getScriptKindFromFileName ( fileName : string ) : ScriptKind {
412
+ const ext = fileName . substr ( fileName . lastIndexOf ( "." ) ) ;
413
+ switch ( ext . toLowerCase ( ) ) {
414
+ case ".js" :
415
+ return ScriptKind . JS ;
416
+ case ".jsx" :
417
+ return ScriptKind . JSX ;
418
+ case ".ts" :
419
+ return ScriptKind . TS ;
420
+ case ".tsx" :
421
+ return ScriptKind . TSX ;
422
+ default :
423
+ return ScriptKind . TS ;
424
+ }
425
+ }
426
+
410
427
// Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
411
428
// indicates what changed between the 'text' that this SourceFile has and the 'newText'.
412
429
// The SourceFile will be created with the compiler attempting to reuse as many nodes from
@@ -533,23 +550,29 @@ namespace ts {
533
550
// attached to the EOF token.
534
551
let parseErrorBeforeNextFinishedNode = false ;
535
552
536
- export function parseSourceFile ( fileName : string , _sourceText : string , languageVersion : ScriptTarget , _syntaxCursor : IncrementalParser . SyntaxCursor , setParentNodes ?: boolean ) : SourceFile {
537
- const isJavaScriptFile = hasJavaScriptFileExtension ( fileName ) || _sourceText . lastIndexOf ( "// @language=javascript" , 0 ) === 0 ;
538
- initializeState ( fileName , _sourceText , languageVersion , isJavaScriptFile , _syntaxCursor ) ;
553
+ export function parseSourceFile ( fileName : string , _sourceText : string , languageVersion : ScriptTarget , _syntaxCursor : IncrementalParser . SyntaxCursor , setParentNodes ?: boolean , scriptKind ?: ScriptKind ) : SourceFile {
554
+ // Using scriptKind as a condition handles both:
555
+ // - 'scriptKind' is unspecified and thus it is `undefined`
556
+ // - 'scriptKind' is set and it is `Unknown` (0)
557
+ // If the 'scriptKind' is 'undefined' or 'Unknown' then attempt
558
+ // to get the ScriptKind from the file name.
559
+ scriptKind = scriptKind ? scriptKind : getScriptKindFromFileName ( fileName ) ;
560
+
561
+ initializeState ( fileName , _sourceText , languageVersion , _syntaxCursor , scriptKind ) ;
539
562
540
- const result = parseSourceFileWorker ( fileName , languageVersion , setParentNodes ) ;
563
+ const result = parseSourceFileWorker ( fileName , languageVersion , setParentNodes , scriptKind ) ;
541
564
542
565
clearState ( ) ;
543
566
544
567
return result ;
545
568
}
546
569
547
- function getLanguageVariant ( fileName : string ) {
570
+ function getLanguageVariant ( scriptKind : ScriptKind ) {
548
571
// .tsx and .jsx files are treated as jsx language variant.
549
- return fileExtensionIs ( fileName , ".tsx" ) || fileExtensionIs ( fileName , ".jsx" ) || fileExtensionIs ( fileName , ".js" ) ? LanguageVariant . JSX : LanguageVariant . Standard ;
572
+ return scriptKind === ScriptKind . TSX || scriptKind === ScriptKind . JSX || scriptKind === ScriptKind . JS ? LanguageVariant . JSX : LanguageVariant . Standard ;
550
573
}
551
574
552
- function initializeState ( fileName : string , _sourceText : string , languageVersion : ScriptTarget , isJavaScriptFile : boolean , _syntaxCursor : IncrementalParser . SyntaxCursor ) {
575
+ function initializeState ( fileName : string , _sourceText : string , languageVersion : ScriptTarget , _syntaxCursor : IncrementalParser . SyntaxCursor , scriptKind : ScriptKind ) {
553
576
NodeConstructor = objectAllocator . getNodeConstructor ( ) ;
554
577
SourceFileConstructor = objectAllocator . getSourceFileConstructor ( ) ;
555
578
@@ -562,14 +585,14 @@ namespace ts {
562
585
identifierCount = 0 ;
563
586
nodeCount = 0 ;
564
587
565
- contextFlags = isJavaScriptFile ? NodeFlags . JavaScriptFile : NodeFlags . None ;
588
+ contextFlags = scriptKind === ScriptKind . JS || scriptKind === ScriptKind . JSX ? NodeFlags . JavaScriptFile : NodeFlags . None ;
566
589
parseErrorBeforeNextFinishedNode = false ;
567
590
568
591
// Initialize and prime the scanner before parsing the source elements.
569
592
scanner . setText ( sourceText ) ;
570
593
scanner . setOnError ( scanError ) ;
571
594
scanner . setScriptTarget ( languageVersion ) ;
572
- scanner . setLanguageVariant ( getLanguageVariant ( fileName ) ) ;
595
+ scanner . setLanguageVariant ( getLanguageVariant ( scriptKind ) ) ;
573
596
}
574
597
575
598
function clearState ( ) {
@@ -585,8 +608,8 @@ namespace ts {
585
608
sourceText = undefined ;
586
609
}
587
610
588
- function parseSourceFileWorker ( fileName : string , languageVersion : ScriptTarget , setParentNodes : boolean ) : SourceFile {
589
- sourceFile = createSourceFile ( fileName , languageVersion ) ;
611
+ function parseSourceFileWorker ( fileName : string , languageVersion : ScriptTarget , setParentNodes : boolean , scriptKind : ScriptKind ) : SourceFile {
612
+ sourceFile = createSourceFile ( fileName , languageVersion , scriptKind ) ;
590
613
sourceFile . flags = contextFlags ;
591
614
592
615
// Prime the scanner.
@@ -653,7 +676,7 @@ namespace ts {
653
676
}
654
677
}
655
678
656
- function createSourceFile ( fileName : string , languageVersion : ScriptTarget ) : SourceFile {
679
+ function createSourceFile ( fileName : string , languageVersion : ScriptTarget , scriptKind : ScriptKind ) : SourceFile {
657
680
// code from createNode is inlined here so createNode won't have to deal with special case of creating source files
658
681
// this is quite rare comparing to other nodes and createNode should be as fast as possible
659
682
const sourceFile = < SourceFile > new SourceFileConstructor ( SyntaxKind . SourceFile , /*pos*/ 0 , /* end */ sourceText . length ) ;
@@ -663,8 +686,9 @@ namespace ts {
663
686
sourceFile . bindDiagnostics = [ ] ;
664
687
sourceFile . languageVersion = languageVersion ;
665
688
sourceFile . fileName = normalizePath ( fileName ) ;
666
- sourceFile . languageVariant = getLanguageVariant ( sourceFile . fileName ) ;
689
+ sourceFile . languageVariant = getLanguageVariant ( scriptKind ) ;
667
690
sourceFile . isDeclarationFile = fileExtensionIs ( sourceFile . fileName , ".d.ts" ) ;
691
+ sourceFile . scriptKind = scriptKind ;
668
692
669
693
return sourceFile ;
670
694
}
@@ -5589,7 +5613,7 @@ namespace ts {
5589
5613
}
5590
5614
5591
5615
export function parseJSDocTypeExpressionForTests ( content : string , start : number , length : number ) {
5592
- initializeState ( "file.js" , content , ScriptTarget . Latest , /*isJavaScriptFile*/ true , /* _syntaxCursor:*/ undefined ) ;
5616
+ initializeState ( "file.js" , content , ScriptTarget . Latest , /*_syntaxCursor:*/ undefined , ScriptKind . JS ) ;
5593
5617
scanner . setText ( content , start , length ) ;
5594
5618
token = scanner . scan ( ) ;
5595
5619
const jsDocTypeExpression = parseJSDocTypeExpression ( ) ;
@@ -5908,7 +5932,7 @@ namespace ts {
5908
5932
}
5909
5933
5910
5934
export function parseIsolatedJSDocComment ( content : string , start : number , length : number ) {
5911
- initializeState ( "file.js" , content , ScriptTarget . Latest , /*isJavaScriptFile*/ true , /* _syntaxCursor:*/ undefined ) ;
5935
+ initializeState ( "file.js" , content , ScriptTarget . Latest , /*_syntaxCursor:*/ undefined , ScriptKind . JS ) ;
5912
5936
sourceFile = < SourceFile > { languageVariant : LanguageVariant . Standard , text : content } ;
5913
5937
const jsDocComment = parseJSDocCommentWorker ( start , length ) ;
5914
5938
const diagnostics = parseDiagnostics ;
@@ -6234,7 +6258,7 @@ namespace ts {
6234
6258
if ( sourceFile . statements . length === 0 ) {
6235
6259
// If we don't have any statements in the current source file, then there's no real
6236
6260
// way to incrementally parse. So just do a full parse instead.
6237
- return Parser . parseSourceFile ( sourceFile . fileName , newText , sourceFile . languageVersion , /*syntaxCursor*/ undefined , /*setParentNodes*/ true ) ;
6261
+ return Parser . parseSourceFile ( sourceFile . fileName , newText , sourceFile . languageVersion , /*syntaxCursor*/ undefined , /*setParentNodes*/ true , sourceFile . scriptKind ) ;
6238
6262
}
6239
6263
6240
6264
// Make sure we're not trying to incrementally update a source file more than once. Once
@@ -6298,7 +6322,7 @@ namespace ts {
6298
6322
// inconsistent tree. Setting the parents on the new tree should be very fast. We
6299
6323
// will immediately bail out of walking any subtrees when we can see that their parents
6300
6324
// are already correct.
6301
- const result = Parser . parseSourceFile ( sourceFile . fileName , newText , sourceFile . languageVersion , syntaxCursor , /*setParentNodes*/ true ) ;
6325
+ const result = Parser . parseSourceFile ( sourceFile . fileName , newText , sourceFile . languageVersion , syntaxCursor , /*setParentNodes*/ true , sourceFile . scriptKind ) ;
6302
6326
6303
6327
return result ;
6304
6328
}
0 commit comments