فهرست منبع

add hover, document symbols

Martin Aeschlimann 6 سال پیش
والد
کامیت
f962c6ee6f
3فایلهای تغییر یافته به همراه127 افزوده شده و 0 حذف شده
  1. 3 0
      src/htmlMode.ts
  2. 12 0
      src/htmlWorker.ts
  3. 112 0
      src/languageFeatures.ts

+ 3 - 0
src/htmlMode.ts

@@ -23,9 +23,12 @@ export function setupMode(defaults: LanguageServiceDefaultsImpl): void {
 
 	// all modes
 	monaco.languages.registerCompletionItemProvider(languageId, new languageFeatures.CompletionAdapter(worker));
+	monaco.languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker));
+
 	monaco.languages.registerDocumentHighlightProvider(languageId, new languageFeatures.DocumentHighlightAdapter(worker));
 	monaco.languages.registerLinkProvider(languageId, new languageFeatures.DocumentLinkAdapter(worker));
 	monaco.languages.registerFoldingRangeProvider(languageId, new languageFeatures.FoldingRangeAdapter(worker));
+	monaco.languages.registerDocumentSymbolProvider(languageId, new languageFeatures.DocumentSymbolAdapter(worker));
 
 	// only html
 	if (languageId === 'html') {

+ 12 - 0
src/htmlWorker.ts

@@ -40,6 +40,12 @@ export class HTMLWorker {
 		let textEdits = this._languageService.format(document, range, this._languageSettings && this._languageSettings.format);
 		return Promise.resolve(textEdits);
 	}
+	doHover(uri: string, position: ls.Position): Thenable<ls.Hover> {
+		let document = this._getTextDocument(uri);
+		let htmlDocument = this._languageService.parseHTMLDocument(document);
+		let hover = this._languageService.doHover(document, position, htmlDocument);
+		return Promise.resolve(hover);
+	}
 	findDocumentHighlights(uri: string, position: ls.Position): Thenable<ls.DocumentHighlight[]> {
 		let document = this._getTextDocument(uri);
 		let htmlDocument = this._languageService.parseHTMLDocument(document);
@@ -51,6 +57,12 @@ export class HTMLWorker {
 		let links = this._languageService.findDocumentLinks(document, null);
 		return Promise.resolve(links);
 	}
+	findDocumentSymbols(uri: string): Thenable<ls.SymbolInformation[]> {
+		let document = this._getTextDocument(uri);
+		let htmlDocument = this._languageService.parseHTMLDocument(document);
+		let symbols = this._languageService.findDocumentSymbols(document, htmlDocument);
+		return Promise.resolve(symbols);
+	}
 	provideFoldingRanges(uri: string, context?: { rangeLimit?: number; }): Thenable<ls.FoldingRange[]> {
 		let document = this._getTextDocument(uri);
 		let ranges = this._languageService.getFoldingRanges(document, context);

+ 112 - 0
src/languageFeatures.ts

@@ -265,6 +265,66 @@ export class CompletionAdapter implements monaco.languages.CompletionItemProvide
 	}
 }
 
+// --- hover ------
+
+function isMarkupContent(thing: any): thing is ls.MarkupContent {
+	return thing && typeof thing === 'object' && typeof (<ls.MarkupContent>thing).kind === 'string';
+}
+
+function toMarkdownString(entry: ls.MarkupContent | ls.MarkedString): monaco.IMarkdownString {
+	if (typeof entry === 'string') {
+		return {
+			value: entry
+		};
+	}
+	if (isMarkupContent(entry)) {
+		if (entry.kind === 'plaintext') {
+			return {
+				value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
+			};
+		}
+		return {
+			value: entry.value
+		};
+	}
+
+	return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' };
+}
+
+function toMarkedStringArray(contents: ls.MarkupContent | ls.MarkedString | ls.MarkedString[]): monaco.IMarkdownString[] {
+	if (!contents) {
+		return void 0;
+	}
+	if (Array.isArray(contents)) {
+		return contents.map(toMarkdownString);
+	}
+	return [toMarkdownString(contents)];
+}
+
+export class HoverAdapter implements monaco.languages.HoverProvider {
+
+	constructor(private _worker: WorkerAccessor) {
+	}
+
+	provideHover(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Hover> {
+		let resource = model.uri;
+
+		return this._worker(resource).then(worker => {
+			return worker.doHover(resource.toString(), fromPosition(position));
+		}).then(info => {
+			if (!info) {
+				return;
+			}
+			return <monaco.languages.Hover>{
+				range: toRange(info.range),
+				contents: toMarkedStringArray(info.contents)
+			};
+		});
+	}
+}
+
+// --- document highlights ------
+
 function toHighlighKind(kind: ls.DocumentHighlightKind): monaco.languages.DocumentHighlightKind {
 	const mKind = monaco.languages.DocumentHighlightKind;
 
@@ -297,6 +357,58 @@ export class DocumentHighlightAdapter implements monaco.languages.DocumentHighli
 	}
 }
 
+// --- document symbols ------
+
+function toSymbolKind(kind: ls.SymbolKind): monaco.languages.SymbolKind {
+	let mKind = monaco.languages.SymbolKind;
+
+	switch (kind) {
+		case ls.SymbolKind.File: return mKind.Array;
+		case ls.SymbolKind.Module: return mKind.Module;
+		case ls.SymbolKind.Namespace: return mKind.Namespace;
+		case ls.SymbolKind.Package: return mKind.Package;
+		case ls.SymbolKind.Class: return mKind.Class;
+		case ls.SymbolKind.Method: return mKind.Method;
+		case ls.SymbolKind.Property: return mKind.Property;
+		case ls.SymbolKind.Field: return mKind.Field;
+		case ls.SymbolKind.Constructor: return mKind.Constructor;
+		case ls.SymbolKind.Enum: return mKind.Enum;
+		case ls.SymbolKind.Interface: return mKind.Interface;
+		case ls.SymbolKind.Function: return mKind.Function;
+		case ls.SymbolKind.Variable: return mKind.Variable;
+		case ls.SymbolKind.Constant: return mKind.Constant;
+		case ls.SymbolKind.String: return mKind.String;
+		case ls.SymbolKind.Number: return mKind.Number;
+		case ls.SymbolKind.Boolean: return mKind.Boolean;
+		case ls.SymbolKind.Array: return mKind.Array;
+	}
+	return mKind.Function;
+}
+
+export class DocumentSymbolAdapter implements monaco.languages.DocumentSymbolProvider {
+
+	constructor(private _worker: WorkerAccessor) {
+	}
+
+	public provideDocumentSymbols(model: monaco.editor.IReadOnlyModel, token: CancellationToken): Thenable<monaco.languages.DocumentSymbol[]> {
+		const resource = model.uri;
+
+		return this._worker(resource).then(worker => worker.findDocumentSymbols(resource.toString())).then(items => {
+			if (!items) {
+				return;
+			}
+			return items.map(item => ({
+				name: item.name,
+				detail: '',
+				containerName: item.containerName,
+				kind: toSymbolKind(item.kind),
+				range: toRange(item.location.range),
+				selectionRange: toRange(item.location.range)
+			}));
+		});
+	}
+}
+
 export class DocumentLinkAdapter implements monaco.languages.LinkProvider {
 
 	constructor(private _worker: WorkerAccessor) {