mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
[html] offer JQuery intellisense
This commit is contained in:
parent
1c4e72aa68
commit
fee99086fb
6
extensions/html/server/lib/OSSREADME.json
Normal file
6
extensions/html/server/lib/OSSREADME.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
|
||||
[{
|
||||
"name": "definitelytyped",
|
||||
"repositoryURL": "https://github.com/DefinitelyTyped/DefinitelyTyped",
|
||||
"license": "MIT"
|
||||
}]
|
3249
extensions/html/server/lib/jquery.d.ts
vendored
Normal file
3249
extensions/html/server/lib/jquery.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -8,9 +8,11 @@ import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache
|
|||
import { TextDocument, Position } from 'vscode-languageserver-types';
|
||||
import { getCSSLanguageService, Stylesheet } from 'vscode-css-languageservice';
|
||||
import { LanguageMode } from './languageModes';
|
||||
import { HTMLDocumentRegions } from './embeddedSupport';
|
||||
|
||||
export function getCSSMode(embeddedCSSDocuments: LanguageModelCache<TextDocument>): LanguageMode {
|
||||
export function getCSSMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>): LanguageMode {
|
||||
let cssLanguageService = getCSSLanguageService();
|
||||
let embeddedCSSDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('css'));
|
||||
let cssStylesheets = getLanguageModelCache<Stylesheet>(10, 60, document => cssLanguageService.parseStylesheet(document));
|
||||
|
||||
return {
|
||||
|
@ -49,9 +51,11 @@ export function getCSSMode(embeddedCSSDocuments: LanguageModelCache<TextDocument
|
|||
return cssLanguageService.findColorSymbols(embedded, cssStylesheets.get(embedded));
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
embeddedCSSDocuments.onDocumentRemoved(document);
|
||||
cssStylesheets.onDocumentRemoved(document);
|
||||
},
|
||||
dispose() {
|
||||
embeddedCSSDocuments.dispose();
|
||||
cssStylesheets.dispose();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,20 +17,78 @@ export interface HTMLDocumentRegions {
|
|||
getLanguageRanges(range: Range): LanguageRange[];
|
||||
getLanguageAtPosition(position: Position): string;
|
||||
getLanguagesInDocument(): string[];
|
||||
getImportedScripts(): string[];
|
||||
}
|
||||
|
||||
interface EmbeddedRegion { languageId: string; start: number; end: number; attributeValue?: boolean; };
|
||||
|
||||
|
||||
export function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {
|
||||
let regions = getEmbeddedRegions(languageService, document);
|
||||
let regions: EmbeddedRegion[] = [];
|
||||
let scanner = languageService.createScanner(document.getText());
|
||||
let lastTagName: string;
|
||||
let lastAttributeName: string;
|
||||
let languageIdFromType: string;
|
||||
let importedScripts = [];
|
||||
|
||||
let token = scanner.scan();
|
||||
while (token !== TokenType.EOS) {
|
||||
switch (token) {
|
||||
case TokenType.StartTag:
|
||||
lastTagName = scanner.getTokenText();
|
||||
lastAttributeName = null;
|
||||
languageIdFromType = 'javascript';
|
||||
break;
|
||||
case TokenType.Styles:
|
||||
regions.push({ languageId: 'css', start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.Script:
|
||||
regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.AttributeName:
|
||||
lastAttributeName = scanner.getTokenText();
|
||||
break;
|
||||
case TokenType.AttributeValue:
|
||||
if (lastAttributeName === 'src' && lastTagName.toLowerCase() === 'script') {
|
||||
let value = scanner.getTokenText();
|
||||
if (value[0] === '\'' || value[0] === '"') {
|
||||
value = value.substr(1, value.length - 1);
|
||||
}
|
||||
importedScripts.push(value);
|
||||
} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
|
||||
if (/["'](text|application)\/(java|ecma)script["']/.test(scanner.getTokenText())) {
|
||||
languageIdFromType = 'javascript';
|
||||
} else {
|
||||
languageIdFromType = void 0;
|
||||
}
|
||||
} else {
|
||||
let attributelLanguageId = getAttributeLanguage(lastAttributeName);
|
||||
if (attributelLanguageId) {
|
||||
let start = scanner.getTokenOffset();
|
||||
let end = scanner.getTokenEnd();
|
||||
let firstChar = document.getText()[start];
|
||||
if (firstChar === '\'' || firstChar === '"') {
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
regions.push({ languageId: attributelLanguageId, start, end, attributeValue: true });
|
||||
}
|
||||
}
|
||||
lastAttributeName = null;
|
||||
break;
|
||||
}
|
||||
token = scanner.scan();
|
||||
}
|
||||
return {
|
||||
getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),
|
||||
getEmbeddedDocument: (languageId: string) => getEmbeddedDocument(document, regions, languageId),
|
||||
getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),
|
||||
getLanguagesInDocument: () => getLanguagesInDocument(document, regions)
|
||||
getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
|
||||
getImportedScripts: () => importedScripts
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getLanguageRanges(document: TextDocument, regions: EmbeddedRegion[], range: Range): LanguageRange[] {
|
||||
let result: LanguageRange[] = [];
|
||||
let currentPos = range ? range.start : Position.create(0, 0);
|
||||
|
@ -164,58 +222,6 @@ function append(result: string, str: string, n: number): string {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getEmbeddedRegions(languageService: LanguageService, document: TextDocument): EmbeddedRegion[] {
|
||||
let regions: EmbeddedRegion[] = [];
|
||||
let scanner = languageService.createScanner(document.getText());
|
||||
let lastTagName: string;
|
||||
let lastAttributeName: string;
|
||||
let languageIdFromType: string;
|
||||
|
||||
let token = scanner.scan();
|
||||
while (token !== TokenType.EOS) {
|
||||
switch (token) {
|
||||
case TokenType.StartTag:
|
||||
lastTagName = scanner.getTokenText();
|
||||
lastAttributeName = null;
|
||||
languageIdFromType = 'javascript';
|
||||
break;
|
||||
case TokenType.Styles:
|
||||
regions.push({ languageId: 'css', start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.Script:
|
||||
regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.AttributeName:
|
||||
lastAttributeName = scanner.getTokenText();
|
||||
break;
|
||||
case TokenType.AttributeValue:
|
||||
if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
|
||||
if (/["'](text|application)\/(java|ecma)script["']/.test(scanner.getTokenText())) {
|
||||
languageIdFromType = 'javascript';
|
||||
} else {
|
||||
languageIdFromType = void 0;
|
||||
}
|
||||
} else {
|
||||
let attributelLanguageId = getAttributeLanguage(lastAttributeName);
|
||||
if (attributelLanguageId) {
|
||||
let start = scanner.getTokenOffset();
|
||||
let end = scanner.getTokenEnd();
|
||||
let firstChar = document.getText()[start];
|
||||
if (firstChar === '\'' || firstChar === '"') {
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
regions.push({ languageId: attributelLanguageId, start, end, attributeValue: true });
|
||||
}
|
||||
}
|
||||
lastAttributeName = null;
|
||||
break;
|
||||
}
|
||||
token = scanner.scan();
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
|
||||
function getAttributeLanguage(attributeName: string): string {
|
||||
let match = attributeName.match(/^(style)|(on\w+)$/i);
|
||||
if (!match) {
|
||||
|
|
|
@ -4,28 +4,33 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { LanguageModelCache } from '../languageModelCache';
|
||||
import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache';
|
||||
import { CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation, Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover, MarkedString, DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions } from 'vscode-languageserver-types';
|
||||
import { LanguageMode } from './languageModes';
|
||||
import { getWordAtText } from '../utils/words';
|
||||
import { HTMLDocumentRegions } from './embeddedSupport';
|
||||
|
||||
import * as ts from 'typescript';
|
||||
import { join } from 'path';
|
||||
|
||||
const FILE_NAME = 'vscode://javascript/1'; // the same 'file' is used for all contents
|
||||
const JQUERY_D_TS = join(__dirname, '../../lib/jquery.d.ts');
|
||||
|
||||
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
|
||||
|
||||
export function getJavascriptMode(jsDocuments: LanguageModelCache<TextDocument>): LanguageMode {
|
||||
export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>): LanguageMode {
|
||||
let jsDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('javascript'));
|
||||
|
||||
let compilerOptions = { allowNonTsExtensions: true, allowJs: true, target: ts.ScriptTarget.Latest };
|
||||
let currentTextDocument: TextDocument;
|
||||
let host = {
|
||||
getCompilationSettings: () => compilerOptions,
|
||||
getScriptFileNames: () => [FILE_NAME],
|
||||
getScriptFileNames: () => [FILE_NAME, JQUERY_D_TS],
|
||||
getScriptVersion: (fileName: string) => {
|
||||
if (fileName === FILE_NAME) {
|
||||
return String(currentTextDocument.version);
|
||||
}
|
||||
return '1'; // default lib is static
|
||||
return '1'; // default lib an jquery.d.ts are static
|
||||
},
|
||||
getScriptSnapshot: (fileName: string) => {
|
||||
let text = fileName === FILE_NAME ? currentTextDocument.getText() : ts.sys.readFile(fileName);
|
||||
|
@ -35,7 +40,7 @@ export function getJavascriptMode(jsDocuments: LanguageModelCache<TextDocument>)
|
|||
getChangeRange: () => void 0
|
||||
};
|
||||
},
|
||||
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
|
||||
getCurrentDirectory: () => '',
|
||||
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options)
|
||||
};
|
||||
let jsLanguageService = ts.createLanguageService(host);
|
||||
|
@ -207,9 +212,11 @@ export function getJavascriptMode(jsDocuments: LanguageModelCache<TextDocument>)
|
|||
return null;
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
jsDocuments.onDocumentRemoved(document);
|
||||
},
|
||||
dispose() {
|
||||
jsLanguageService.dispose();
|
||||
jsDocuments.dispose();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -60,14 +60,10 @@ export function getLanguageModes(supportedLanguages: { [languageId: string]: boo
|
|||
let modes = {};
|
||||
modes['html'] = getHTMLMode(htmlLanguageService);
|
||||
if (supportedLanguages['css']) {
|
||||
let embeddedCSSDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('css'));
|
||||
modelCaches.push(embeddedCSSDocuments);
|
||||
modes['css'] = getCSSMode(embeddedCSSDocuments);
|
||||
modes['css'] = getCSSMode(documentRegions);
|
||||
}
|
||||
if (supportedLanguages['javascript']) {
|
||||
let embeddedJSDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('javascript'));
|
||||
modelCaches.push(embeddedJSDocuments);
|
||||
modes['javascript'] = getJavascriptMode(embeddedJSDocuments);
|
||||
modes['javascript'] = getJavascriptMode(documentRegions);
|
||||
}
|
||||
return {
|
||||
getModeAtPosition(document: TextDocument, position: Position): LanguageMode {
|
||||
|
|
|
@ -22,10 +22,9 @@ suite('HTML Javascript Support', () => {
|
|||
|
||||
let document = TextDocument.create('test://test/test.html', 'html', 0, value);
|
||||
|
||||
let documentRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document);
|
||||
let documentRegions = getLanguageModelCache<embeddedSupport.HTMLDocumentRegions>(10, 60, document => embeddedSupport.getDocumentRegions(htmlLanguageService, document));
|
||||
|
||||
let embeddedJSDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.getEmbeddedDocument('javascript'));
|
||||
var mode = getJavascriptMode(embeddedJSDocuments);
|
||||
var mode = getJavascriptMode(documentRegions);
|
||||
|
||||
let position = document.positionAt(offset);
|
||||
let list = mode.doComplete(document, position);
|
||||
|
@ -40,5 +39,6 @@ suite('HTML Javascript Support', () => {
|
|||
|
||||
test('Completions', function (): any {
|
||||
assertCompletions('<html><script>window.|</script></html>', ['location']);
|
||||
assertCompletions('<html><script>$.|</script></html>', ['getJSON']);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue