Skip to content

Commit 6f53296

Browse files
committed
Support sourcing files
- Only variables found in the sourced files are completed on - Jump to definition works on the source file path (e.g. clicking "source my-file.sh")
1 parent fee79d2 commit 6f53296

File tree

5 files changed

+301
-135
lines changed

5 files changed

+301
-135
lines changed

server/src/__tests__/__snapshots__/analyzer.test.ts.snap

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,6 @@ Array [
3838
]
3939
`;
4040

41-
exports[`findDefinition returns a list of locations if parameter is found 1`] = `
42-
Array [
43-
Object {
44-
"range": Object {
45-
"end": Object {
46-
"character": 37,
47-
"line": 148,
48-
},
49-
"start": Object {
50-
"character": 0,
51-
"line": 148,
52-
},
53-
},
54-
"uri": "dummy-uri.sh",
55-
},
56-
]
57-
`;
58-
5941
exports[`findReferences returns a list of locations if parameter is found 1`] = `
6042
Array [
6143
Object {

server/src/__tests__/analyzer.test.ts

Lines changed: 122 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import FIXTURES, { FIXTURE_FOLDER } from '../../../testing/fixtures'
1+
import FIXTURES, { FIXTURE_FOLDER, FIXTURE_URI } from '../../../testing/fixtures'
22
import { getMockConnection } from '../../../testing/mocks'
33
import Analyzer from '../analyser'
44
import { initializeParser } from '../parser'
@@ -8,6 +8,9 @@ let analyzer: Analyzer
88

99
const CURRENT_URI = 'dummy-uri.sh'
1010

11+
// if you add a .sh file to testing/fixtures, update this value
12+
const FIXTURE_FILES_MATCHING_GLOB = 11
13+
1114
beforeAll(async () => {
1215
const parser = await initializeParser()
1316
analyzer = new Analyzer(parser)
@@ -33,17 +36,62 @@ describe('analyze', () => {
3336
})
3437

3538
describe('findDefinition', () => {
36-
it('returns empty list if parameter is not found', () => {
39+
it('returns an empty list if word is not found', () => {
3740
analyzer.analyze(CURRENT_URI, FIXTURES.INSTALL)
38-
const result = analyzer.findDefinition('foobar')
41+
const result = analyzer.findDefinition({ uri: CURRENT_URI, word: 'foobar' })
3942
expect(result).toEqual([])
4043
})
4144

45+
it('returns a location to a file if word is the path in a sourcing statement', () => {
46+
analyzer.analyze(CURRENT_URI, FIXTURES.SOURCING)
47+
const result = analyzer.findDefinition({
48+
uri: CURRENT_URI,
49+
word: './extension.inc',
50+
position: { character: 10, line: 2 },
51+
})
52+
expect(result).toMatchInlineSnapshot(`
53+
Array [
54+
Object {
55+
"range": Object {
56+
"end": Object {
57+
"character": 0,
58+
"line": 0,
59+
},
60+
"start": Object {
61+
"character": 0,
62+
"line": 0,
63+
},
64+
},
65+
"uri": "extension.inc",
66+
},
67+
]
68+
`)
69+
})
70+
4271
it('returns a list of locations if parameter is found', () => {
4372
analyzer.analyze(CURRENT_URI, FIXTURES.INSTALL)
44-
const result = analyzer.findDefinition('node_version')
73+
const result = analyzer.findDefinition({
74+
uri: CURRENT_URI,
75+
word: 'node_version',
76+
})
4577
expect(result).not.toEqual([])
46-
expect(result).toMatchSnapshot()
78+
expect(result).toMatchInlineSnapshot(`
79+
Array [
80+
Object {
81+
"range": Object {
82+
"end": Object {
83+
"character": 37,
84+
"line": 148,
85+
},
86+
"start": Object {
87+
"character": 0,
88+
"line": 148,
89+
},
90+
},
91+
"uri": "dummy-uri.sh",
92+
},
93+
]
94+
`)
4795
})
4896
})
4997

@@ -84,6 +132,50 @@ describe('findSymbolsForFile', () => {
84132
})
85133
})
86134

135+
describe('findAllSourcedUris', () => {
136+
it('returns references to sourced files', async () => {
137+
const parser = await initializeParser()
138+
const connection = getMockConnection()
139+
140+
const newAnalyzer = await Analyzer.fromRoot({
141+
connection,
142+
rootPath: FIXTURE_FOLDER,
143+
parser,
144+
})
145+
146+
const result = newAnalyzer.findAllSourcedUris({ uri: FIXTURE_URI.SOURCING })
147+
expect(result).toEqual(
148+
new Set([
149+
`file://${FIXTURE_FOLDER}issue101.sh`,
150+
`file://${FIXTURE_FOLDER}extension.inc`,
151+
]),
152+
)
153+
})
154+
155+
it('returns references to sourced files without file extension', async () => {
156+
const parser = await initializeParser()
157+
const connection = getMockConnection()
158+
159+
const newAnalyzer = await Analyzer.fromRoot({
160+
connection,
161+
rootPath: FIXTURE_FOLDER,
162+
parser,
163+
})
164+
165+
// Parse the file without extension
166+
newAnalyzer.analyze(FIXTURE_URI.MISSING_EXTENSION, FIXTURES.MISSING_EXTENSION)
167+
168+
const result = newAnalyzer.findAllSourcedUris({ uri: FIXTURE_URI.MISSING_EXTENSION })
169+
expect(result).toEqual(
170+
new Set([
171+
`file://${FIXTURE_FOLDER}extension.inc`,
172+
`file://${FIXTURE_FOLDER}issue101.sh`,
173+
`file://${FIXTURE_FOLDER}sourcing.sh`,
174+
]),
175+
)
176+
})
177+
})
178+
87179
describe('wordAtPoint', () => {
88180
it('returns current word at a given point', () => {
89181
analyzer.analyze(CURRENT_URI, FIXTURES.INSTALL)
@@ -112,92 +204,41 @@ describe('wordAtPoint', () => {
112204
})
113205
})
114206

115-
describe('findSymbolCompletions', () => {
207+
describe('findSymbolsMatchingWord', () => {
116208
it('return a list of symbols across the workspace', () => {
117209
analyzer.analyze('install.sh', FIXTURES.INSTALL)
118210
analyzer.analyze('sourcing-sh', FIXTURES.SOURCING)
119211

120212
expect(
121-
analyzer.findSymbolsMatchingWord({ word: 'npm_config_logl', exactMatch: false }),
122-
).toMatchInlineSnapshot(`
123-
Array [
124-
Object {
125-
"kind": 13,
126-
"location": Object {
127-
"range": Object {
128-
"end": Object {
129-
"character": 27,
130-
"line": 40,
131-
},
132-
"start": Object {
133-
"character": 0,
134-
"line": 40,
135-
},
136-
},
137-
"uri": "dummy-uri.sh",
138-
},
139-
"name": "npm_config_loglevel",
140-
},
141-
Object {
142-
"kind": 13,
143-
"location": Object {
144-
"range": Object {
145-
"end": Object {
146-
"character": 31,
147-
"line": 48,
148-
},
149-
"start": Object {
150-
"character": 2,
151-
"line": 48,
152-
},
153-
},
154-
"uri": "dummy-uri.sh",
155-
},
156-
"name": "npm_config_loglevel",
157-
},
158-
Object {
159-
"kind": 13,
160-
"location": Object {
161-
"range": Object {
162-
"end": Object {
163-
"character": 27,
164-
"line": 40,
165-
},
166-
"start": Object {
167-
"character": 0,
168-
"line": 40,
169-
},
170-
},
171-
"uri": "install.sh",
172-
},
173-
"name": "npm_config_loglevel",
174-
},
175-
Object {
176-
"kind": 13,
177-
"location": Object {
178-
"range": Object {
179-
"end": Object {
180-
"character": 31,
181-
"line": 48,
182-
},
183-
"start": Object {
184-
"character": 2,
185-
"line": 48,
186-
},
187-
},
188-
"uri": "install.sh",
189-
},
190-
"name": "npm_config_loglevel",
191-
},
192-
]
193-
`)
213+
analyzer.findSymbolsMatchingWord({
214+
word: 'npm_config_logl',
215+
uri: FIXTURE_URI.INSTALL,
216+
exactMatch: false,
217+
}),
218+
).toMatchInlineSnapshot(`Array []`)
194219

195220
expect(
196-
analyzer.findSymbolsMatchingWord({ word: 'xxxxxxxx', exactMatch: false }),
221+
analyzer.findSymbolsMatchingWord({
222+
word: 'xxxxxxxx',
223+
uri: FIXTURE_URI.INSTALL,
224+
exactMatch: false,
225+
}),
197226
).toMatchInlineSnapshot(`Array []`)
198227

199228
expect(
200-
analyzer.findSymbolsMatchingWord({ word: 'BLU', exactMatch: false }),
229+
analyzer.findSymbolsMatchingWord({
230+
word: 'BLU',
231+
uri: FIXTURE_URI.INSTALL,
232+
exactMatch: false,
233+
}),
234+
).toMatchInlineSnapshot(`Array []`)
235+
236+
expect(
237+
analyzer.findSymbolsMatchingWord({
238+
word: 'BLU',
239+
uri: FIXTURE_URI.SOURCING,
240+
exactMatch: false,
241+
}),
201242
).toMatchInlineSnapshot(`Array []`)
202243
})
203244
})
@@ -249,9 +290,6 @@ describe('fromRoot', () => {
249290

250291
expect(connection.window.showWarningMessage).not.toHaveBeenCalled()
251292

252-
// if you add a .sh file to testing/fixtures, update this value
253-
const FIXTURE_FILES_MATCHING_GLOB = 11
254-
255293
// Intro, stats on glob, one file skipped due to shebang, and outro
256294
const LOG_LINES = FIXTURE_FILES_MATCHING_GLOB + 4
257295

server/src/__tests__/server.test.ts

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,83 @@ Helper function to add a user",
464464
{} as any,
465465
)
466466

467-
// they are all variables
468-
expect(Array.from(new Set(result.map((item: any) => item.kind)))).toEqual([
469-
lsp.CompletionItemKind.Variable,
470-
])
467+
expect(result).toMatchInlineSnapshot(`
468+
Array [
469+
Object {
470+
"data": Object {
471+
"name": "BOLD",
472+
"type": 3,
473+
},
474+
"documentation": undefined,
475+
"kind": 6,
476+
"label": "BOLD",
477+
},
478+
Object {
479+
"data": Object {
480+
"name": "RED",
481+
"type": 3,
482+
},
483+
"documentation": "Variable defined in ../extension.inc",
484+
"kind": 6,
485+
"label": "RED",
486+
},
487+
Object {
488+
"data": Object {
489+
"name": "GREEN",
490+
"type": 3,
491+
},
492+
"documentation": "Variable defined in ../extension.inc",
493+
"kind": 6,
494+
"label": "GREEN",
495+
},
496+
Object {
497+
"data": Object {
498+
"name": "BLUE",
499+
"type": 3,
500+
},
501+
"documentation": "Variable defined in ../extension.inc",
502+
"kind": 6,
503+
"label": "BLUE",
504+
},
505+
Object {
506+
"data": Object {
507+
"name": "RESET",
508+
"type": 3,
509+
},
510+
"documentation": "Variable defined in ../extension.inc",
511+
"kind": 6,
512+
"label": "RESET",
513+
},
514+
Object {
515+
"data": Object {
516+
"name": "USER",
517+
"type": 3,
518+
},
519+
"documentation": "Variable defined in ../issue101.sh",
520+
"kind": 6,
521+
"label": "USER",
522+
},
523+
Object {
524+
"data": Object {
525+
"name": "PASSWORD",
526+
"type": 3,
527+
},
528+
"documentation": "Variable defined in ../issue101.sh",
529+
"kind": 6,
530+
"label": "PASSWORD",
531+
},
532+
Object {
533+
"data": Object {
534+
"name": "COMMENTS",
535+
"type": 3,
536+
},
537+
"documentation": "Variable defined in ../issue101.sh
538+
539+
Having shifted twice, the rest is now comments ...",
540+
"kind": 6,
541+
"label": "COMMENTS",
542+
},
543+
]
544+
`)
471545
})
472546
})

0 commit comments

Comments
 (0)