Skip to content

Commit

Permalink
feat: support for twoslash queries
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Oct 15, 2022
1 parent ec49410 commit 7b7147c
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
Expand Up @@ -17,6 +17,7 @@ import useReferencesCodeLensPlugin from './plugins/vue-codelens-references';
import useHtmlPugConversionsPlugin from './plugins/vue-convert-htmlpug';
import useRefSugarConversionsPlugin from './plugins/vue-convert-refsugar';
import useScriptSetupConversionsPlugin from './plugins/vue-convert-scriptsetup';
import useTwoslashQueries from './plugins/vue-twoslash-queries';
import useVueTemplateLanguagePlugin, { semanticTokenTypes as vueTemplateSemanticTokenTypes } from './plugins/vue-template';

export function getSemanticTokenLegend() {
Expand Down Expand Up @@ -96,6 +97,9 @@ export function getLanguageServicePlugins(
vueLsHost: host,
context: apis.context,
});
const twoslashQueriesPlugin = useTwoslashQueries({
getVueDocument: (document) => apis.context.documents.get(document.uri),
});

return [
vuePlugin,
Expand All @@ -111,6 +115,7 @@ export function getLanguageServicePlugins(
autoDotValuePlugin,
// put emmet plugin at last to fix https://github.com/johnsoncodehk/volar/issues/1088
emmetPlugin,
twoslashQueriesPlugin,
];
}

Expand Down
@@ -0,0 +1,75 @@
import { EmbeddedFileKind, forEachEmbeddeds, LanguageServicePlugin, LanguageServicePluginContext, SourceFileDocument } from '@volar/language-service';
import * as vue from '@volar/vue-language-core';
import * as vscode from 'vscode-languageserver-protocol';
import { TextDocument } from 'vscode-languageserver-textdocument';

export default function (options: {
getVueDocument(document: TextDocument): SourceFileDocument | undefined,
}): LanguageServicePlugin {

let context: LanguageServicePluginContext;

return {

setup(_context) {
context = _context;
},

inlayHints: {

on(document, range) {
return worker(document, (vueDocument, vueFile) => {

const ts = context.typescript.module;
const hoverOffsets: [vscode.Position, number][] = [];
const inlayHints: vscode.InlayHint[] = [];

for (const pointer of document.getText(range).matchAll(/\^\?/g)) {
const offset = pointer.index! + document.offsetAt(range.start);
const position = document.positionAt(offset);
hoverOffsets.push([position, document.offsetAt({
line: position.line - 1,
character: position.character,
})]);
}

forEachEmbeddeds(vueFile.embeddeds, (embedded) => {
if (embedded.kind === EmbeddedFileKind.TypeScriptHostFile) {
const sourceMap = vueDocument.getSourceMap(embedded);
for (const [pointerPosition, hoverOffset] of hoverOffsets) {
for (const [tsOffset, mapping] of sourceMap.toGeneratedOffsets(hoverOffset)) {
if (mapping.data.hover) {
const quickInfo = context.typescript.languageService.getQuickInfoAtPosition(embedded.fileName, tsOffset);
if (quickInfo) {
inlayHints.push({
position: { line: pointerPosition.line, character: pointerPosition.character + 2 },
label: ts.displayPartsToString(quickInfo.displayParts),
paddingLeft: true,
paddingRight: false,
});
}
break;
}
}
}
}
});

return inlayHints;
});
},
},
};

function worker<T>(document: TextDocument, callback: (vueDocument: SourceFileDocument, vueSourceFile: vue.VueSourceFile) => T) {

const vueDocument = options.getVueDocument(document);
if (!vueDocument)
return;

if (!(vueDocument.file instanceof vue.VueSourceFile))
return;

return callback(vueDocument, vueDocument.file);
}
}

0 comments on commit 7b7147c

Please sign in to comment.