diff --git a/src/htmlMode.ts b/src/htmlMode.ts
index 29204df7..da96f530 100644
--- a/src/htmlMode.ts
+++ b/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') {
diff --git a/src/htmlWorker.ts b/src/htmlWorker.ts
index 130e649d..23014475 100644
--- a/src/htmlWorker.ts
+++ b/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 {
+ 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 {
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 {
+ 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 {
let document = this._getTextDocument(uri);
let ranges = this._languageService.getFoldingRanges(document, context);
diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts
index 3ae813ee..8950044c 100644
--- a/src/languageFeatures.ts
+++ b/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 (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 {
+ let resource = model.uri;
+
+ return this._worker(resource).then(worker => {
+ return worker.doHover(resource.toString(), fromPosition(position));
+ }).then(info => {
+ if (!info) {
+ return;
+ }
+ return {
+ 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 {
+ 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) {