Skip to content

Commit

Permalink
Use typescript parser (#294)
Browse files Browse the repository at this point in the history
* use typescript parser and generate code without rewriting script code

* resolve variable definition
  • Loading branch information
znck committed Oct 3, 2022
1 parent f6af2b3 commit 1adb9f3
Show file tree
Hide file tree
Showing 59 changed files with 3,175 additions and 2,600 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"onwarn",
"textdocument",
"treeshake",
"tsserverlibrary",
"typecheck",
"ucfirst",
"Uncapitalize",
Expand Down
157 changes: 96 additions & 61 deletions extensions/vscode-vue-language-features/src/scheme/vue.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isVueFile, parseFileName } from '@vuedx/shared'
import { first, isNotNull, parseFileName } from '@vuedx/shared'
import { TextSpan } from '@vuedx/vue-virtual-textdocument'
import { inject, injectable } from 'inversify'
import vscode from 'vscode'
import vscode, { TextEditor } from 'vscode'
import { PluginCommunicationService } from '../services/PluginCommunicationService'
import { Installable } from '../utils/installable'
import { getVirtualFileNameFromUri } from '../utils/uri'
Expand All @@ -18,17 +19,20 @@ export class VueVirtualDocumentProvider
}

private readonly openVueFiles = new Map<string, Set<string>>()
private readonly decoration = vscode.window.createTextEditorDecorationType({
outline: 'solid red 1px',
})

private editors: readonly TextEditor[] = []

public install(): vscode.Disposable {
super.install()

let selectionWatcher: vscode.Disposable | undefined
let cancellationToken: vscode.CancellationTokenSource | undefined

return vscode.Disposable.from(
vscode.workspace.registerTextDocumentContentProvider('vue', this),
vscode.workspace.onDidChangeTextDocument(({ document }) => {
vscode.workspace.onDidChangeTextDocument(async ({ document }) => {
if (document.languageId === 'vue') {
await delay(100)
this.openVueFiles.get(document.fileName)?.forEach((uri) => {
this.onDidChangeEmitter.fire(vscode.Uri.parse(uri))
})
Expand Down Expand Up @@ -56,72 +60,103 @@ export class VueVirtualDocumentProvider
if (openFiles.size === 0) this.openVueFiles.delete(parsed.fileName)
}
}),
vscode.window.onDidChangeActiveTextEditor((editor) => {
selectionWatcher?.dispose()
if (editor == null || !isVueFile(editor.document.fileName)) return
const fileName = editor.document.fileName

selectionWatcher = vscode.window.onDidChangeTextEditorSelection(
async ({ textEditor, selections }) => {
if (textEditor !== editor) return // ignore others
if (selections.length !== 1) return
if (
!vscode.window.visibleTextEditors.some(
(editor) =>
parseFileName(editor.document.fileName).fileName === fileName,
)
) {
return // No active virtual document
}

cancellationToken?.cancel()
const current = new vscode.CancellationTokenSource()
cancellationToken = current

const start = textEditor.document.offsetAt(editor.selection.start)
const end = textEditor.document.offsetAt(editor.selection.end)
const result = await this.plugin.first(async (_conneciton) => {
console.log(start, end)
return null as null | {
fileName: string
start: number
end: number
} // TODO: fix this
})

// not found or cancelled
if (result == null || current.token.isCancellationRequested) return

const virtualEditor = vscode.window.visibleTextEditors.find(
(editor) => editor.document.fileName === result.fileName,
vscode.window.onDidChangeActiveTextEditor(() => {
this.resetAllDecorations()
}),
vscode.window.onDidChangeVisibleTextEditors((editors) => {
this.editors = editors
}),
vscode.window.onDidChangeTextEditorSelection(
async ({ textEditor, selections }) => {
if (textEditor !== vscode.window.activeTextEditor) return
if (textEditor.document.languageId === 'vue') {
const fileName = textEditor.document.fileName
const editor = this.editors.find(
(editor) =>
editor.document.uri.scheme === 'vue' &&
editor.document.fileName.startsWith(fileName),
)

if (virtualEditor == null) return // not active

const range = new vscode.Range(
virtualEditor.document.positionAt(result.start),
virtualEditor.document.positionAt(result.end),
if (editor == null) return
const textSpans = await Promise.all(
selections.map(
async (selection) =>
await this.plugin.first(async (connection) => {
const start = textEditor.document.offsetAt(selection.start)
const end = textEditor.document.offsetAt(selection.end)

return await connection.findGeneratedTextSpan(fileName, {
start: Math.min(start, end),
length: Math.abs(end - start),
})
}),
),
)

virtualEditor.options.cursorStyle =
vscode.TextEditorCursorStyle.Underline
virtualEditor.selection = new vscode.Selection(
range.start,
range.end,
this.setDecorations(textSpans, editor)
} else if (textEditor.document.uri.scheme === 'vue') {
const fileName = textEditor.document.fileName.replace(
/\.[tj]sx$/,
'',
)
virtualEditor.revealRange(
range,
vscode.TextEditorRevealType.Default,
const editor = this.editors.find((editor) =>
editor.document.fileName.startsWith(fileName),
)
},
)
}),

if (editor == null) return
const textSpans = await Promise.all(
selections.map(
async (selection) =>
await this.plugin.first(async (connection) => {
const start = textEditor.document.offsetAt(selection.start)
const end = textEditor.document.offsetAt(selection.end)

return await connection.findOriginalTextSpan(fileName, {
start: Math.min(start, end),
length: Math.abs(end - start),
})
}),
),
)
this.setDecorations(textSpans, editor)
}
},
),
)
}

private readonly onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>()
public onDidChange = this.onDidChangeEmitter.event

private resetAllDecorations(): void {
this.editors.forEach((editor) => {
editor.setDecorations(this.decoration, [])
})
}

private setDecorations(
textSpans: Array<TextSpan | null | undefined>,
editor: vscode.TextEditor,
): void {
const ranges = textSpans
.filter(isNotNull)
.map(
(range) =>
new vscode.Range(
editor.document.positionAt(range.start),
editor.document.positionAt(range.start + range.length),
),
)

editor.setDecorations(this.decoration, [])
editor.setDecorations(this.decoration, ranges)
if (ranges.length > 0) {
editor.revealRange(
first(ranges),
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
)
}
}

async provideTextDocumentContent(
request: vscode.Uri,
): Promise<string | undefined> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import {
isProjectRuntimeFile,
isVueFile,
parseFileName,
toFileName
toFileName,
} from '@vuedx/shared'
import { } from '@vuedx/vue-virtual-textdocument'
import { inject, injectable } from 'inversify'
import {
Disposable,
StatusBarAlignment,
StatusBarItem,
TextEditor,
Uri,
window
window,
} from 'vscode'
import { Installable } from '../utils/installable'
import { getVirtualFileUri } from '../utils/uri'
Expand Down Expand Up @@ -41,8 +40,8 @@ export class VirtualFileSwitcher extends Installable {
window.onDidChangeActiveTextEditor(async (editor) => {
await this.showStatusBar(editor)
}),
this.plugin.onChange(() => {
void this.showStatusBar(window.activeTextEditor)
this.plugin.onChange(async () => {
await this.showStatusBar(window.activeTextEditor)
}),
)
}
Expand Down
2 changes: 0 additions & 2 deletions packages/compiler-tsx/compiler-tsx.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ export interface CompileOutput extends TransformedCode {
errors: Array<CompilerError | SyntaxError>;
// (undocumented)
template?: RootNode;
// (undocumented)
unusedIdentifiers: string[];
}

// @public (undocumented)
Expand Down
Loading

0 comments on commit 1adb9f3

Please sign in to comment.