languageModes.ts 5.6 KB
Newer Older
1 2 3 4
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
5

6
import { getLanguageService as getHTMLLanguageService, DocumentContext, HTMLData } from 'vscode-html-languageservice';
7 8
import {
	CompletionItem, Location, SignatureHelp, Definition, TextEdit, TextDocument, Diagnostic, DocumentLink, Range,
9
	Hover, DocumentHighlight, CompletionList, Position, FormattingOptions, SymbolInformation, FoldingRange
10
} from 'vscode-languageserver-types';
11
import { ColorInformation, ColorPresentation, Color, WorkspaceFolder } from 'vscode-languageserver';
12

13 14
import { getLanguageModelCache, LanguageModelCache } from '../languageModelCache';
import { getDocumentRegions, HTMLDocumentRegions } from './embeddedSupport';
15
import { getCSSMode } from './cssMode';
16
import { getJavaScriptMode } from './javascriptMode';
17 18
import { getHTMLMode } from './htmlMode';

M
Martin Aeschlimann 已提交
19
export { ColorInformation, ColorPresentation, Color };
20

21 22 23 24 25 26
export interface Settings {
	css?: any;
	html?: any;
	javascript?: any;
}

27 28 29
export interface Workspace {
	readonly settings: Settings;
	readonly folders: WorkspaceFolder[];
30 31
}

32
export interface LanguageMode {
33
	getId(): string;
P
Pine Wu 已提交
34
	doSelection?: (document: TextDocument, position: Position) => Range[];
35
	doValidation?: (document: TextDocument, settings?: Settings) => Diagnostic[];
36
	doComplete?: (document: TextDocument, position: Position, settings?: Settings) => CompletionList;
37
	doResolve?: (document: TextDocument, item: CompletionItem) => CompletionItem;
38 39
	doHover?: (document: TextDocument, position: Position) => Hover | null;
	doSignatureHelp?: (document: TextDocument, position: Position) => SignatureHelp | null;
40
	findDocumentHighlight?: (document: TextDocument, position: Position) => DocumentHighlight[];
41
	findDocumentSymbols?: (document: TextDocument) => SymbolInformation[];
42
	findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext) => DocumentLink[];
43
	findDefinition?: (document: TextDocument, position: Position) => Definition | null;
44
	findReferences?: (document: TextDocument, position: Position) => Location[];
45
	format?: (document: TextDocument, range: Range, options: FormattingOptions, settings?: Settings) => TextEdit[];
46
	findDocumentColors?: (document: TextDocument) => ColorInformation[];
M
Martin Aeschlimann 已提交
47
	getColorPresentations?: (document: TextDocument, color: Color, range: Range) => ColorPresentation[];
48
	doAutoClose?: (document: TextDocument, position: Position) => string | null;
49
	getFoldingRanges?: (document: TextDocument) => FoldingRange[];
50 51 52 53 54
	onDocumentRemoved(document: TextDocument): void;
	dispose(): void;
}

export interface LanguageModes {
55
	getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined;
56
	getModesInRange(document: TextDocument, range: Range): LanguageModeRange[];
57
	getAllModes(): LanguageMode[];
58
	getAllModesInDocument(document: TextDocument): LanguageMode[];
59
	getMode(languageId: string): LanguageMode | undefined;
60 61
	onDocumentRemoved(document: TextDocument): void;
	dispose(): void;
62 63
}

64
export interface LanguageModeRange extends Range {
65
	mode: LanguageMode | undefined;
66
	attributeValue?: boolean;
67 68
}

69
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }, workspace: Workspace, customData?: HTMLData): LanguageModes {
P
Pine Wu 已提交
70 71
	const customDataCollections = customData ? [customData] : [];
	const htmlLanguageService = getHTMLLanguageService({ customDataCollections });
72

73
	let documentRegions = getLanguageModelCache<HTMLDocumentRegions>(10, 60, document => getDocumentRegions(htmlLanguageService, document));
74

75 76 77
	let modelCaches: LanguageModelCache<any>[] = [];
	modelCaches.push(documentRegions);

78
	let modes = Object.create(null);
79
	modes['html'] = getHTMLMode(htmlLanguageService, workspace);
80
	if (supportedLanguages['css']) {
81
		modes['css'] = getCSSMode(documentRegions, workspace);
82 83
	}
	if (supportedLanguages['javascript']) {
M
Matt Bierner 已提交
84
		modes['javascript'] = getJavaScriptMode(documentRegions);
85
	}
86
	return {
87
		getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined {
88
			let languageId = documentRegions.get(document).getLanguageAtPosition(position);
89 90 91
			if (languageId) {
				return modes[languageId];
			}
R
Rob Lourens 已提交
92
			return undefined;
93
		},
94
		getModesInRange(document: TextDocument, range: Range): LanguageModeRange[] {
95
			return documentRegions.get(document).getLanguageRanges(range).map(r => {
96
				return <LanguageModeRange>{
97 98
					start: r.start,
					end: r.end,
99
					mode: r.languageId && modes[r.languageId],
100
					attributeValue: r.attributeValue
101 102 103
				};
			});
		},
104
		getAllModesInDocument(document: TextDocument): LanguageMode[] {
105
			let result = [];
106 107 108
			for (let languageId of documentRegions.get(document).getLanguagesInDocument()) {
				let mode = modes[languageId];
				if (mode) {
109
					result.push(mode);
110 111
				}
			}
112
			return result;
113
		},
114 115 116 117 118 119 120 121 122 123 124 125
		getAllModes(): LanguageMode[] {
			let result = [];
			for (let languageId in modes) {
				let mode = modes[languageId];
				if (mode) {
					result.push(mode);
				}
			}
			return result;
		},
		getMode(languageId: string): LanguageMode {
			return modes[languageId];
126 127 128 129 130 131 132 133 134 135 136 137 138 139
		},
		onDocumentRemoved(document: TextDocument) {
			modelCaches.forEach(mc => mc.onDocumentRemoved(document));
			for (let mode in modes) {
				modes[mode].onDocumentRemoved(document);
			}
		},
		dispose(): void {
			modelCaches.forEach(mc => mc.dispose());
			modelCaches = [];
			for (let mode in modes) {
				modes[mode].dispose();
			}
			modes = {};
140 141 142
		}
	};
}