Skip to content

Commit a71fa45

Browse files
committed
Salsa: adding ScriptKind to ensure script blocks (.html, .aspx, .ascx, etc) are processed as JS
1 parent af9dc41 commit a71fa45

6 files changed

Lines changed: 67 additions & 32 deletions

File tree

src/compiler/parser.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,15 @@ namespace ts {
399399
}
400400
}
401401

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 {
403403
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);
405405

406406
parseTime += new Date().getTime() - start;
407407
return result;
408408
}
409409

410+
410411
// Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
411412
// indicates what changed between the 'text' that this SourceFile has and the 'newText'.
412413
// The SourceFile will be created with the compiler attempting to reuse as many nodes from
@@ -416,8 +417,8 @@ namespace ts {
416417
// from this SourceFile that are being held onto may change as a result (including
417418
// becoming detached from any SourceFile). It is recommended that this SourceFile not
418419
// be used once 'update' is called on it.
419-
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
420-
return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
420+
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean, scriptKind?: ScriptKind): SourceFile {
421+
return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks, scriptKind);
421422
}
422423

423424
/* @internal */
@@ -533,8 +534,10 @@ namespace ts {
533534
// attached to the EOF token.
534535
let parseErrorBeforeNextFinishedNode = false;
535536

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;
537+
export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
538+
539+
const isJavaScriptFile = hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0 || scriptKind == ScriptKind.Js;
540+
538541
initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor);
539542

540543
const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes);
@@ -6222,7 +6225,7 @@ namespace ts {
62226225
}
62236226

62246227
namespace IncrementalParser {
6225-
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile {
6228+
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean, scriptKind?: ScriptKind): SourceFile {
62266229
aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
62276230

62286231
checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
@@ -6234,7 +6237,7 @@ namespace ts {
62346237
if (sourceFile.statements.length === 0) {
62356238
// If we don't have any statements in the current source file, then there's no real
62366239
// way to incrementally parse. So just do a full parse instead.
6237-
return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true);
6240+
return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, scriptKind);
62386241
}
62396242

62406243
// Make sure we're not trying to incrementally update a source file more than once. Once
@@ -6298,7 +6301,7 @@ namespace ts {
62986301
// inconsistent tree. Setting the parents on the new tree should be very fast. We
62996302
// will immediately bail out of walking any subtrees when we can see that their parents
63006303
// are already correct.
6301-
const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true);
6304+
const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, scriptKind);
63026305

63036306
return result;
63046307
}

src/compiler/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
namespace ts {
23
export interface Map<T> {
34
[index: string]: T;
@@ -2459,6 +2460,14 @@ namespace ts {
24592460
character: number;
24602461
}
24612462

2463+
export const enum ScriptKind {
2464+
Unknown = 0,
2465+
Js = 1,
2466+
Jsx = 2,
2467+
Ts = 3,
2468+
Tsx = 4
2469+
}
2470+
24622471
export const enum ScriptTarget {
24632472
ES3 = 0,
24642473
ES5 = 1,

src/harness/harnessLanguageService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ namespace Harness.LanguageService {
183183
const script = this.getScriptInfo(fileName);
184184
return script ? new ScriptSnapshot(script) : undefined;
185185
}
186+
getScriptKind(fileName: string): ScriptKind { return ScriptKind.Unknown; }
186187
getScriptVersion(fileName: string): string {
187188
const script = this.getScriptInfo(fileName);
188189
return script ? script.version.toString() : undefined;
@@ -253,6 +254,7 @@ namespace Harness.LanguageService {
253254
const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName);
254255
return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot);
255256
}
257+
getScriptKind(fileName: string): ScriptKind { return this.nativeHost.getScriptKind(fileName); }
256258
getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); }
257259
getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); }
258260

src/server/editorServices.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ namespace ts.server {
192192
return this.roots.map(root => root.fileName);
193193
}
194194

195+
getScriptKind() {
196+
return ScriptKind.Unknown;
197+
}
198+
195199
getScriptVersion(filename: string) {
196200
return this.getScriptInfo(filename).svc.latestVersion().toString();
197201
}

src/services/services.ts

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,8 @@ namespace ts {
819819
super(kind, pos, end);
820820
}
821821

822-
public update(newText: string, textChangeRange: TextChangeRange): SourceFile {
823-
return updateSourceFile(this, newText, textChangeRange);
822+
public update(newText: string, textChangeRange: TextChangeRange, scriptKind?: ScriptKind): SourceFile {
823+
return updateSourceFile(this, newText, textChangeRange, /*aggressiveChecks*/ undefined, scriptKind);
824824
}
825825

826826
public getLineAndCharacterOfPosition(position: number): LineAndCharacter {
@@ -1019,6 +1019,7 @@ namespace ts {
10191019
getNewLine?(): string;
10201020
getProjectVersion?(): string;
10211021
getScriptFileNames(): string[];
1022+
getScriptKind(fileName: string): ScriptKind;
10221023
getScriptVersion(fileName: string): string;
10231024
getScriptSnapshot(fileName: string): IScriptSnapshot;
10241025
getLocalizedDiagnosticMessages?(): any;
@@ -1468,7 +1469,8 @@ namespace ts {
14681469
fileName: string,
14691470
compilationSettings: CompilerOptions,
14701471
scriptSnapshot: IScriptSnapshot,
1471-
version: string): SourceFile;
1472+
version: string,
1473+
scriptKind?: ScriptKind): SourceFile;
14721474

14731475
/**
14741476
* Request an updated version of an already existing SourceFile with a given fileName
@@ -1486,7 +1488,8 @@ namespace ts {
14861488
fileName: string,
14871489
compilationSettings: CompilerOptions,
14881490
scriptSnapshot: IScriptSnapshot,
1489-
version: string): SourceFile;
1491+
version: string,
1492+
scriptKind?: ScriptKind): SourceFile;
14901493

14911494
/**
14921495
* Informs the DocumentRegistry that a file is not needed any longer.
@@ -1657,6 +1660,7 @@ namespace ts {
16571660
hostFileName: string;
16581661
version: string;
16591662
scriptSnapshot: IScriptSnapshot;
1663+
scriptKind: ScriptKind;
16601664
}
16611665

16621666
interface DocumentRegistryEntry {
@@ -1746,12 +1750,14 @@ namespace ts {
17461750

17471751
private createEntry(fileName: string, path: Path) {
17481752
let entry: HostFileInformation;
1753+
const scriptKind = this.host.getScriptKind(fileName);
17491754
const scriptSnapshot = this.host.getScriptSnapshot(fileName);
17501755
if (scriptSnapshot) {
17511756
entry = {
17521757
hostFileName: fileName,
17531758
version: this.host.getScriptVersion(fileName),
1754-
scriptSnapshot: scriptSnapshot
1759+
scriptSnapshot: scriptSnapshot,
1760+
scriptKind: scriptKind
17551761
};
17561762
}
17571763

@@ -1817,17 +1823,18 @@ namespace ts {
18171823
throw new Error("Could not find file: '" + fileName + "'.");
18181824
}
18191825

1826+
const scriptKind = this.host.getScriptKind(fileName);
18201827
const version = this.host.getScriptVersion(fileName);
18211828
let sourceFile: SourceFile;
18221829

18231830
if (this.currentFileName !== fileName) {
18241831
// This is a new file, just parse it
1825-
sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true);
1832+
sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true, scriptKind);
18261833
}
18271834
else if (this.currentFileVersion !== version) {
18281835
// This is the same file, just a newer version. Incrementally parse the file.
18291836
const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
1830-
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
1837+
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange, /*aggressiveChecks*/ undefined, scriptKind);
18311838
}
18321839

18331840
if (sourceFile) {
@@ -1953,16 +1960,16 @@ namespace ts {
19531960
return output.outputText;
19541961
}
19551962

1956-
export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile {
1963+
export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile {
19571964
const text = scriptSnapshot.getText(0, scriptSnapshot.getLength());
1958-
const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents);
1965+
const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind);
19591966
setSourceFileFields(sourceFile, scriptSnapshot, version);
19601967
return sourceFile;
19611968
}
19621969

19631970
export let disableIncrementalParsing = false;
19641971

1965-
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
1972+
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean, scriptKind?: ScriptKind): SourceFile {
19661973
// If we were given a text change range, and our version or open-ness changed, then
19671974
// incrementally parse this file.
19681975
if (textChangeRange) {
@@ -1996,7 +2003,7 @@ namespace ts {
19962003
: (changedText + suffix);
19972004
}
19982005

1999-
const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
2006+
const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks, scriptKind);
20002007
setSourceFileFields(newSourceFile, scriptSnapshot, version);
20012008
// after incremental parsing nameTable might not be up-to-date
20022009
// drop it so it can be lazily recreated later
@@ -2017,7 +2024,7 @@ namespace ts {
20172024
}
20182025

20192026
// Otherwise, just create a new source file.
2020-
return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true);
2027+
return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, scriptKind);
20212028
}
20222029

20232030
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
@@ -2059,20 +2066,21 @@ namespace ts {
20592066
return JSON.stringify(bucketInfoArray, undefined, 2);
20602067
}
20612068

2062-
function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
2063-
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true);
2069+
function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
2070+
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true, scriptKind);
20642071
}
20652072

2066-
function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
2067-
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false);
2073+
function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
2074+
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false, scriptKind);
20682075
}
20692076

20702077
function acquireOrUpdateDocument(
20712078
fileName: string,
20722079
compilationSettings: CompilerOptions,
20732080
scriptSnapshot: IScriptSnapshot,
20742081
version: string,
2075-
acquiring: boolean): SourceFile {
2082+
acquiring: boolean,
2083+
scriptKind?: ScriptKind): SourceFile {
20762084

20772085
const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
20782086
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
@@ -2081,7 +2089,7 @@ namespace ts {
20812089
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
20822090

20832091
// Have never seen this file with these settings. Create a new source file for it.
2084-
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false);
2092+
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
20852093

20862094
entry = {
20872095
sourceFile: sourceFile,
@@ -2095,8 +2103,8 @@ namespace ts {
20952103
// the script snapshot. If so, update it appropriately. Otherwise, we can just
20962104
// return it as is.
20972105
if (entry.sourceFile.version !== version) {
2098-
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
2099-
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
2106+
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
2107+
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot), /*aggressiveChecks*/ undefined, scriptKind);
21002108
}
21012109
}
21022110

@@ -2848,14 +2856,14 @@ namespace ts {
28482856
// it's source file any more, and instead defers to DocumentRegistry to get
28492857
// either version 1, version 2 (or some other version) depending on what the
28502858
// host says should be used.
2851-
return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
2859+
return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind);
28522860
}
28532861

28542862
// We didn't already have the file. Fall through and acquire it from the registry.
28552863
}
28562864

28572865
// Could not find this file in the old program, create a new SourceFile for it.
2858-
return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
2866+
return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind);
28592867
}
28602868

28612869
function sourceFileUpToDate(sourceFile: SourceFile): boolean {
@@ -4641,7 +4649,7 @@ namespace ts {
46414649

46424650
// Go to the original declaration for cases:
46434651
//
4644-
// (1) when the aliased symbol was declared in the location(parent).
4652+
// (1) when the aliased symbol was declared in the location(parent).
46454653
// (2) when the aliased symbol is originating from a named import.
46464654
//
46474655
if (node.kind === SyntaxKind.Identifier &&

src/services/shims.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace ts {
5555

5656
/** Returns a JSON-encoded value of the type: string[] */
5757
getScriptFileNames(): string;
58+
getScriptKind(fileName: string): ScriptKind;
5859
getScriptVersion(fileName: string): string;
5960
getScriptSnapshot(fileName: string): ScriptSnapshotShim;
6061
getLocalizedDiagnosticMessages(): string;
@@ -346,6 +347,14 @@ namespace ts {
346347
return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
347348
}
348349

350+
public getScriptKind(fileName: string): ScriptKind {
351+
try {
352+
return this.shimHost.getScriptKind(fileName);
353+
} catch (e) {
354+
return ScriptKind.Unknown;
355+
}
356+
}
357+
349358
public getScriptVersion(fileName: string): string {
350359
return this.shimHost.getScriptVersion(fileName);
351360
}

0 commit comments

Comments
 (0)