Skip to content

Commit e451a84

Browse files
committed
refactor: move resolveStaticString to util/tree-sitter.ts
This seemed the most appropriate place for it.
1 parent f0416f8 commit e451a84

File tree

2 files changed

+40
-31
lines changed

2 files changed

+40
-31
lines changed

server/src/util/sourcing.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { untildify } from './fs'
99
import * as TreeSitterUtil from './tree-sitter'
1010

1111
const SOURCING_COMMANDS = ['source', '.']
12-
const VARIABLE_NODE_TYPES = ['expansion', 'simple_expansion']
1312

1413
export type SourceCommand = {
1514
range: LSP.Range
@@ -103,7 +102,7 @@ function getSourcedPathInfoFromNode({
103102
}
104103
}
105104

106-
const strValue = resolveStaticString(argumentNode)
105+
const strValue = TreeSitterUtil.resolveStaticString(argumentNode)
107106
if (strValue !== null) {
108107
return {
109108
sourcedPath: strValue,
@@ -113,7 +112,7 @@ function getSourcedPathInfoFromNode({
113112
// Strip one leading dynamic section.
114113
if (argumentNode.type === 'string' && argumentNode.namedChildren.length === 1) {
115114
const [variableNode] = argumentNode.namedChildren
116-
if (VARIABLE_NODE_TYPES.includes(variableNode.type)) {
115+
if (TreeSitterUtil.isExpansion(variableNode)) {
117116
const stringContents = argumentNode.text.slice(1, -1)
118117
if (stringContents.startsWith(`${variableNode.text}/`)) {
119118
return {
@@ -192,22 +191,22 @@ function resolveSourcedUri({
192191
*/
193192
function resolveSourceFromConcatenation(node: Parser.SyntaxNode): string | null {
194193
if (node.type !== 'concatenation') return null
195-
const stringValue = resolveStaticString(node)
194+
const stringValue = TreeSitterUtil.resolveStaticString(node)
196195
if (stringValue !== null) return stringValue // This string is fully static.
197196

198197
const values: string[] = []
199198
// Since the string must begin with the variable, the variable must be in the first child.
200199
const [firstNode, ...rest] = node.namedChildren
201200
// The first child is static, this means one of the other children is not!
202-
if (resolveStaticString(firstNode) !== null) return null
201+
if (TreeSitterUtil.resolveStaticString(firstNode) !== null) return null
203202

204203
// if the string is unquoted, the first child is the variable, so there's no more text in it.
205-
if (!VARIABLE_NODE_TYPES.includes(firstNode.type)) {
204+
if (!TreeSitterUtil.isExpansion(firstNode)) {
206205
if (firstNode.namedChildCount > 1) return null // Only one variable is allowed.
207206
// Since the string must begin with the variable, the variable must be first child.
208207
const variableNode = firstNode.namedChildren[0] // Get the variable (quoted case)
209208
// This is command substitution!
210-
if (!VARIABLE_NODE_TYPES.includes(variableNode.type)) return null
209+
if (!TreeSitterUtil.isExpansion(variableNode)) return null
211210
const stringContents = firstNode.text.slice(1, -1)
212211
// The string doesn't start with the variable!
213212
if (!stringContents.startsWith(variableNode.text)) return null
@@ -216,7 +215,7 @@ function resolveSourceFromConcatenation(node: Parser.SyntaxNode): string | null
216215
}
217216

218217
for (const child of rest) {
219-
const value = resolveStaticString(child)
218+
const value = TreeSitterUtil.resolveStaticString(child)
220219
// The other values weren't statically determinable!
221220
if (value === null) return null
222221
values.push(value)
@@ -230,26 +229,3 @@ function resolveSourceFromConcatenation(node: Parser.SyntaxNode): string | null
230229
// PERF: can we fail earlier than this?
231230
return null
232231
}
233-
234-
/**
235-
* Resolves the full string value of a node
236-
* Returns null if the value can't be statically determined (ie, it contains a variable or command substition).
237-
* Supports: word, string, raw_string, and concatenation
238-
*/
239-
function resolveStaticString(node: Parser.SyntaxNode): string | null {
240-
if (node.type === 'concatenation') {
241-
const values = []
242-
for (const child of node.namedChildren) {
243-
const value = resolveStaticString(child)
244-
if (value === null) return null
245-
values.push(value)
246-
}
247-
return values.join('')
248-
}
249-
if (node.type === 'word') return node.text
250-
if (node.type === 'string' || node.type === 'raw_string') {
251-
if (node.namedChildCount === 0) return node.text.slice(1, -1)
252-
return null
253-
}
254-
return null
255-
}

server/src/util/tree-sitter.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ export function isReference(n: SyntaxNode): boolean {
4343
}
4444
}
4545

46+
export function isExpansion(n: SyntaxNode): boolean {
47+
switch (n.type) {
48+
case 'expansion':
49+
case 'simple_expansion':
50+
return true
51+
default:
52+
return false
53+
}
54+
}
55+
4656
export function findParent(
4757
start: SyntaxNode,
4858
predicate: (n: SyntaxNode) => boolean,
@@ -64,3 +74,26 @@ export function findParentOfType(start: SyntaxNode, type: string | string[]) {
6474

6575
return findParent(start, (n) => type.includes(n.type))
6676
}
77+
78+
/**
79+
* Resolves the full string value of a node
80+
* Returns null if the value can't be statically determined (ie, it contains a variable or command substition).
81+
* Supports: word, string, raw_string, and concatenation
82+
*/
83+
export function resolveStaticString(node: SyntaxNode): string | null {
84+
if (node.type === 'concatenation') {
85+
const values = []
86+
for (const child of node.namedChildren) {
87+
const value = resolveStaticString(child)
88+
if (value === null) return null
89+
values.push(value)
90+
}
91+
return values.join('')
92+
}
93+
if (node.type === 'word') return node.text
94+
if (node.type === 'string' || node.type === 'raw_string') {
95+
if (node.namedChildCount === 0) return node.text.slice(1, -1)
96+
return null
97+
}
98+
return null
99+
}

0 commit comments

Comments
 (0)