Skip to content

Commit c4d2ee5

Browse files
committed
feat: getNodePath API command. Add relativeOffset to API request options as API commonly used with -1 offset
1 parent 7fb376d commit c4d2ee5

File tree

5 files changed

+59
-30
lines changed

5 files changed

+59
-30
lines changed

src/extension.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
import * as vscode from 'vscode'
33
import { defaultJsSupersetLangs } from '@zardoy/vscode-utils/build/langs'
44
import { getActiveRegularEditor } from '@zardoy/vscode-utils'
5-
import { extensionCtx, getExtensionSettingId, getExtensionCommandId } from 'vscode-framework'
5+
import { extensionCtx, getExtensionSettingId, getExtensionCommandId, registerActiveDevelopmentCommand } from 'vscode-framework'
66
import { pickObj } from '@zardoy/utils'
7+
import { TriggerCharacterCommand } from '../typescript/src/ipcTypes'
78
import { Configuration } from './configurationType'
89
import webImports from './webImports'
910
import { sendCommand } from './sendCommand'
@@ -76,15 +77,22 @@ export const activateTsPlugin = (tsApi: { configurePlugin; onCompletionAccepted
7677
}
7778
})
7879

80+
const sharedRequest = (type: TriggerCharacterCommand, { offset, relativeOffset = 0 }: RequestOptions) => {
81+
const { activeTextEditor } = vscode.window
82+
if (!activeTextEditor) return
83+
const { document, selection } = activeTextEditor
84+
offset ??= document.offsetAt(selection.active) + relativeOffset
85+
return sendCommand(type, { document, position: document.positionAt(offset) })
86+
}
87+
7988
type RequestOptions = Partial<{
8089
offset: number
90+
relativeOffset: number
8191
}>
82-
vscode.commands.registerCommand(getExtensionCommandId('getNodeAtPosition' as never), async ({ offset }: RequestOptions = {}) => {
83-
const { activeTextEditor } = vscode.window
84-
if (!activeTextEditor) return
85-
const { document } = activeTextEditor
86-
return sendCommand('nodeAtPosition', { document, position: offset ? document.positionAt(offset) : activeTextEditor.selection.active })
87-
})
92+
vscode.commands.registerCommand(getExtensionCommandId('getNodeAtPosition' as never), async (options: RequestOptions = {}) =>
93+
sharedRequest('nodeAtPosition', options),
94+
)
95+
vscode.commands.registerCommand(getExtensionCommandId('getNodePath' as never), async (options: RequestOptions = {}) => sharedRequest('nodePath', options))
8896

8997
if (process.env.PLATFORM === 'web') {
9098
const possiblySyncConfig = async () => {

typescript/src/completions/isGoodPositionMethodCompletion.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GetConfig } from '../types'
33
import { findChildContainingPosition, findChildContainingPositionMaxDepth } from '../utils'
44

55
export const isGoodPositionBuiltinMethodCompletion = (ts: typeof tslib, sourceFile: ts.SourceFile, position: number, c: GetConfig) => {
6-
const importClauseCandidate = findChildContainingPositionMaxDepth(ts, sourceFile, position, 3)
6+
const importClauseCandidate = findChildContainingPositionMaxDepth(sourceFile, position, 3)
77
if (importClauseCandidate && ts.isImportClause(importClauseCandidate)) return false
88
const textBeforePos = sourceFile.getFullText().slice(position - 1, position)
99
let currentNode = findChildContainingPosition(ts, sourceFile, textBeforePos === ':' ? position - 1 : position)

typescript/src/ipcTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const triggerCharacterCommands = ['find-in-import', 'getPostfixes', 'nodeAtPosition', 'emmet-completions'] as const
1+
export const triggerCharacterCommands = ['find-in-import', 'getPostfixes', 'nodeAtPosition', 'nodePath', 'emmet-completions'] as const
22
export type TriggerCharacterCommand = typeof triggerCharacterCommands[number]
33

44
export type NodeAtPositionResponse = {

typescript/src/specialCommands/handle.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import postfixesAtPosition from '../completions/postfixesAtPosition'
22
import { NodeAtPositionResponse, TriggerCharacterCommand, triggerCharacterCommands } from '../ipcTypes'
3-
import { findChildContainingPosition } from '../utils'
3+
import { findChildContainingPosition, getNodePath } from '../utils'
44
import getEmmetCompletions from './emmet'
55

66
export default (
@@ -29,13 +29,14 @@ export default (
2929
const node = findChildContainingPosition(ts, sourceFile, position)
3030
return {
3131
entries: [],
32-
typescriptEssentialsResponse: !node
33-
? undefined
34-
: ({
35-
kindName: ts.SyntaxKind[node.kind],
36-
start: node.getStart(),
37-
end: node.getEnd(),
38-
} as NodeAtPositionResponse),
32+
typescriptEssentialsResponse: !node ? undefined : nodeToApiResponse(node),
33+
}
34+
}
35+
if (specialCommand === 'nodePath') {
36+
const nodes = getNodePath(sourceFile, position)
37+
return {
38+
entries: [],
39+
typescriptEssentialsResponse: nodes.map(node => nodeToApiResponse(node)),
3940
}
4041
}
4142
if (specialCommand === 'getPostfixes') {
@@ -47,3 +48,11 @@ export default (
4748
} as any
4849
}
4950
}
51+
52+
function nodeToApiResponse(node: ts.Node): NodeAtPositionResponse {
53+
return {
54+
kindName: ts.SyntaxKind[node.kind]!,
55+
start: node.getStart(),
56+
end: node.getEnd(),
57+
}
58+
}

typescript/src/utils.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import type tslib from 'typescript/lib/tsserverlibrary'
22
import { SetOptional } from 'type-fest'
33

4-
export function findChildContainingPosition(
5-
typescript: typeof import('typescript/lib/tsserverlibrary'),
6-
sourceFile: ts.SourceFile,
7-
position: number,
8-
): ts.Node | undefined {
4+
export function findChildContainingPosition(typescript: typeof tslib, sourceFile: ts.SourceFile, position: number): ts.Node | undefined {
95
function find(node: ts.Node): ts.Node | undefined {
106
if (position >= node.getStart() && position < node.getEnd()) {
117
return typescript.forEachChild(node, find) || node
@@ -16,25 +12,41 @@ export function findChildContainingPosition(
1612
return find(sourceFile)
1713
}
1814

19-
export function findChildContainingPositionMaxDepth(
20-
typescript: typeof import('typescript/lib/tsserverlibrary'),
21-
sourceFile: ts.SourceFile,
22-
position: number,
23-
maxDepth?: number,
24-
): ts.Node | undefined {
15+
export function findChildContainingPositionMaxDepth(sourceFile: ts.SourceFile, position: number, maxDepth?: number): ts.Node | undefined {
2516
let currentDepth = 0
2617
function find(node: ts.Node): ts.Node | undefined {
2718
if (position >= node.getStart() && position < node.getEnd()) {
2819
if (++currentDepth === maxDepth) return node
29-
return typescript.forEachChild(node, find) || node
20+
return ts.forEachChild(node, find) || node
3021
}
3122

3223
return
3324
}
3425
return find(sourceFile)
3526
}
3627

37-
export const getIndentFromPos = (typescript: typeof import('typescript/lib/tsserverlibrary'), sourceFile: ts.SourceFile, position: number) => {
28+
export function getNodePath(sourceFile: ts.SourceFile, position: number): ts.Node[] {
29+
const nodes: ts.Node[] = []
30+
function find(node: ts.Node): ts.Node | undefined {
31+
if (position >= node.getStart() && position < node.getEnd()) {
32+
if (node !== sourceFile) nodes.push(node)
33+
return ts.forEachChild(node, find) || node
34+
}
35+
36+
return
37+
}
38+
find(sourceFile)
39+
return nodes
40+
}
41+
42+
// todo not impl
43+
type MatchStringValue = keyof typeof ts.SyntaxKind | '*'
44+
45+
export const matchNodePath = (sourceFile: ts.SourceFile, position: number, candidates: MatchStringValue[][]) => {
46+
const nodesPath = getNodePath(sourceFile, position)
47+
}
48+
49+
export const getIndentFromPos = (typescript: typeof tslib, sourceFile: ts.SourceFile, position: number) => {
3850
const { character } = typescript.getLineAndCharacterOfPosition(sourceFile, position)
3951
return (
4052
sourceFile

0 commit comments

Comments
 (0)