Skip to content

Commit 0d5c9f4

Browse files
authored
Remove Need for File Extensions in TypeScript Language Definitions (#26413)
Part of #25740 To support TS Server plugins for languages like angular, we will allow extensions to register new langauges for TypeScript to watch. The angular language for example would want ng-html files to also be uploaded to TypeScript for checking The current language definitions all define both a set of language modes they support and a set of file extensions. The file extension part is unnessiary and may be incorrect depending on how a user sets up their `file.associations` in the workspace. This change removes the extensions part so that we always make use of the language mode
1 parent 97f1fc6 commit 0d5c9f4

File tree

2 files changed

+73
-72
lines changed

2 files changed

+73
-72
lines changed

extensions/typescript/src/features/bufferSyncSupport.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ export default class BufferSyncSupport {
107107

108108
private _validate: boolean;
109109
private modeIds: ObjectMap<boolean>;
110-
private extensions: ObjectMap<boolean>;
111110
private diagnostics: Diagnostics;
112111
private disposables: Disposable[] = [];
113112
private syncedBuffers: ObjectMap<SyncedBuffer>;
@@ -119,12 +118,11 @@ export default class BufferSyncSupport {
119118
private emitQueue: LinkedMap<string>;
120119
private checkGlobalTSCVersion: boolean;
121120

122-
constructor(client: ITypescriptServiceClient, modeIds: string[], diagnostics: Diagnostics, extensions: ObjectMap<boolean>, validate: boolean = true) {
121+
constructor(client: ITypescriptServiceClient, modeIds: string[], diagnostics: Diagnostics, validate: boolean = true) {
123122
this.client = client;
124123
this.modeIds = Object.create(null);
125124
modeIds.forEach(modeId => this.modeIds[modeId] = true);
126125
this.diagnostics = diagnostics;
127-
this.extensions = extensions;
128126
this._validate = validate;
129127

130128
this.projectValidationRequested = false;

extensions/typescript/src/typescriptMain.ts

Lines changed: 72 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* ------------------------------------------------------------------------------------------ */
1010
'use strict';
1111

12-
import { env, languages, commands, workspace, window, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, Disposable, Uri, MessageItem, TextEditor, DiagnosticSeverity } from 'vscode';
12+
import { env, languages, commands, workspace, window, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, Disposable, Uri, MessageItem, TextEditor, DiagnosticSeverity, TextDocument } from 'vscode';
1313

1414
// This must be the first statement otherwise modules might got loaded with
1515
// the wrong locale.
@@ -54,7 +54,6 @@ interface LanguageDescription {
5454
id: string;
5555
diagnosticSource: string;
5656
modeIds: string[];
57-
extensions: string[];
5857
configFile: string;
5958
}
6059

@@ -79,14 +78,12 @@ export function activate(context: ExtensionContext): void {
7978
id: 'typescript',
8079
diagnosticSource: 'ts',
8180
modeIds: [MODE_ID_TS, MODE_ID_TSX],
82-
extensions: ['.ts', '.tsx'],
8381
configFile: 'tsconfig.json'
8482
},
8583
{
8684
id: 'javascript',
8785
diagnosticSource: 'js',
8886
modeIds: [MODE_ID_JS, MODE_ID_JSX],
89-
extensions: ['.js', '.jsx', '.es6', '.mjs'],
9087
configFile: 'jsconfig.json'
9188
}
9289
], context.storagePath, context.globalState, context.workspaceState);
@@ -136,8 +133,6 @@ export function activate(context: ExtensionContext): void {
136133
const validateSetting = 'validate.enable';
137134

138135
class LanguageProvider {
139-
140-
private readonly extensions: ObjectMap<boolean>;
141136
private syntaxDiagnostics: ObjectMap<Diagnostic[]>;
142137
private readonly currentDiagnostics: DiagnosticCollection;
143138
private readonly bufferSyncSupport: BufferSyncSupport;
@@ -160,14 +155,11 @@ class LanguageProvider {
160155
private readonly client: TypeScriptServiceClient,
161156
private readonly description: LanguageDescription
162157
) {
163-
this.extensions = Object.create(null);
164-
description.extensions.forEach(extension => this.extensions[extension] = true);
165-
166158
this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds, {
167159
delete: (file: string) => {
168160
this.currentDiagnostics.delete(client.asUrl(file));
169161
}
170-
}, this.extensions);
162+
});
171163
this.syntaxDiagnostics = Object.create(null);
172164
this.currentDiagnostics = languages.createDiagnosticCollection(description.id);
173165

@@ -334,13 +326,20 @@ class LanguageProvider {
334326
}
335327
}
336328

337-
public handles(file: string): boolean {
338-
const extension = path.extname(file);
339-
if ((extension && this.extensions[extension]) || this.bufferSyncSupport.handles(file)) {
329+
public handles(file: string, doc: TextDocument): boolean {
330+
if (doc && this.description.modeIds.indexOf(doc.languageId) >= 0) {
340331
return true;
341332
}
333+
334+
if (this.bufferSyncSupport.handles(file)) {
335+
return true;
336+
}
337+
342338
const basename = path.basename(file);
343-
return !!basename && basename === this.description.configFile;
339+
if (!!basename && basename === this.description.configFile) {
340+
return true;
341+
}
342+
return false;
344343
}
345344

346345
public get id(): string {
@@ -558,14 +557,15 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
558557
});
559558
}
560559

561-
private findLanguage(file: string): LanguageProvider | null {
562-
for (let i = 0; i < this.languages.length; i++) {
563-
let language = this.languages[i];
564-
if (language.handles(file)) {
565-
return language;
560+
private findLanguage(file: string): Thenable<LanguageProvider | null> {
561+
return workspace.openTextDocument(file).then((doc: TextDocument) => {
562+
for (const language of this.languages) {
563+
if (language.handles(file, doc)) {
564+
return language;
565+
}
566566
}
567-
}
568-
return null;
567+
return null;
568+
}, () => null);
569569
}
570570

571571
private triggerAllDiagnostics() {
@@ -580,22 +580,24 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
580580
}
581581

582582
/* internal */ syntaxDiagnosticsReceived(event: Proto.DiagnosticEvent): void {
583-
let body = event.body;
583+
const body = event.body;
584584
if (body && body.diagnostics) {
585-
let language = this.findLanguage(body.file);
586-
if (language) {
587-
language.syntaxDiagnosticsReceived(body.file, this.createMarkerDatas(body.diagnostics, language.diagnosticSource));
588-
}
585+
this.findLanguage(body.file).then(language => {
586+
if (language) {
587+
language.syntaxDiagnosticsReceived(body.file, this.createMarkerDatas(body.diagnostics, language.diagnosticSource));
588+
}
589+
});
589590
}
590591
}
591592

592593
/* internal */ semanticDiagnosticsReceived(event: Proto.DiagnosticEvent): void {
593-
let body = event.body;
594+
const body = event.body;
594595
if (body && body.diagnostics) {
595-
let language = this.findLanguage(body.file);
596-
if (language) {
597-
language.semanticDiagnosticsReceived(body.file, this.createMarkerDatas(body.diagnostics, language.diagnosticSource));
598-
}
596+
this.findLanguage(body.file).then(language => {
597+
if (language) {
598+
language.semanticDiagnosticsReceived(body.file, this.createMarkerDatas(body.diagnostics, language.diagnosticSource));
599+
}
600+
});
599601
}
600602
/*
601603
if (Is.defined(body.queueLength)) {
@@ -611,47 +613,48 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
611613
return;
612614
}
613615

614-
const language = body.triggerFile ? this.findLanguage(body.triggerFile) : this.findLanguage(body.configFile);
615-
if (!language) {
616-
return;
617-
}
618-
if (body.diagnostics.length === 0) {
619-
language.configFileDiagnosticsReceived(body.configFile, []);
620-
} else if (body.diagnostics.length >= 1) {
621-
workspace.openTextDocument(Uri.file(body.configFile)).then((document) => {
622-
let curly: [number, number, number] | undefined = undefined;
623-
let nonCurly: [number, number, number] | undefined = undefined;
624-
let diagnostic: Diagnostic;
625-
for (let index = 0; index < document.lineCount; index++) {
626-
const line = document.lineAt(index);
627-
const text = line.text;
628-
const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex;
629-
if (firstNonWhitespaceCharacterIndex < text.length) {
630-
if (text.charAt(firstNonWhitespaceCharacterIndex) === '{') {
631-
curly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + 1];
632-
break;
633-
} else {
634-
const matches = /\s*([^\s]*)(?:\s*|$)/.exec(text.substr(firstNonWhitespaceCharacterIndex));
635-
if (matches && matches.length >= 1) {
636-
nonCurly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + matches[1].length];
616+
(body.triggerFile ? this.findLanguage(body.triggerFile) : this.findLanguage(body.configFile)).then(language => {
617+
if (!language) {
618+
return;
619+
}
620+
if (body.diagnostics.length === 0) {
621+
language.configFileDiagnosticsReceived(body.configFile, []);
622+
} else if (body.diagnostics.length >= 1) {
623+
workspace.openTextDocument(Uri.file(body.configFile)).then((document) => {
624+
let curly: [number, number, number] | undefined = undefined;
625+
let nonCurly: [number, number, number] | undefined = undefined;
626+
let diagnostic: Diagnostic;
627+
for (let index = 0; index < document.lineCount; index++) {
628+
const line = document.lineAt(index);
629+
const text = line.text;
630+
const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex;
631+
if (firstNonWhitespaceCharacterIndex < text.length) {
632+
if (text.charAt(firstNonWhitespaceCharacterIndex) === '{') {
633+
curly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + 1];
634+
break;
635+
} else {
636+
const matches = /\s*([^\s]*)(?:\s*|$)/.exec(text.substr(firstNonWhitespaceCharacterIndex));
637+
if (matches && matches.length >= 1) {
638+
nonCurly = [index, firstNonWhitespaceCharacterIndex, firstNonWhitespaceCharacterIndex + matches[1].length];
639+
}
637640
}
638641
}
639642
}
640-
}
641-
const match = curly || nonCurly;
642-
if (match) {
643-
diagnostic = new Diagnostic(new Range(match[0], match[1], match[0], match[2]), body.diagnostics[0].text);
644-
} else {
645-
diagnostic = new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text);
646-
}
647-
if (diagnostic) {
648-
diagnostic.source = language.diagnosticSource;
649-
language.configFileDiagnosticsReceived(body.configFile, [diagnostic]);
650-
}
651-
}, _error => {
652-
language.configFileDiagnosticsReceived(body.configFile, [new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text)]);
653-
});
654-
}
643+
const match = curly || nonCurly;
644+
if (match) {
645+
diagnostic = new Diagnostic(new Range(match[0], match[1], match[0], match[2]), body.diagnostics[0].text);
646+
} else {
647+
diagnostic = new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text);
648+
}
649+
if (diagnostic) {
650+
diagnostic.source = language.diagnosticSource;
651+
language.configFileDiagnosticsReceived(body.configFile, [diagnostic]);
652+
}
653+
}, _error => {
654+
language.configFileDiagnosticsReceived(body.configFile, [new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text)]);
655+
});
656+
}
657+
});
655658
}
656659

657660
private createMarkerDatas(diagnostics: Proto.Diagnostic[], source: string): Diagnostic[] {

0 commit comments

Comments
 (0)