Skip to content

Commit 7bf48d4

Browse files
authored
Merge pull request #677 from machty/machty-auto-import
Auto Imports, remove JS/TS config
2 parents d11ebfb + f416758 commit 7bf48d4

File tree

10 files changed

+508
-132
lines changed

10 files changed

+508
-132
lines changed

Diff for: .vscode/launch.json

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"version": "0.2.0",
33
"configurations": [
44
{
5-
"name": "Debug Extension",
5+
"name": "Debug Extension (Glint + TS)",
66
"type": "extensionHost",
77
"request": "launch",
88
"preLaunchTask": "npm: build",
@@ -16,6 +16,24 @@
1616
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode",
1717
"${workspaceFolder}/test-packages"
1818
]
19+
},
20+
{
21+
"name": "Debug Extension (Glint Only, No TS)",
22+
"type": "extensionHost",
23+
"request": "launch",
24+
"preLaunchTask": "npm: build",
25+
"autoAttachChildProcesses": true,
26+
"runtimeExecutable": "${execPath}",
27+
"outFiles": [
28+
"${workspaceFolder}/**/*.js",
29+
"!**/node_modules/**"
30+
],
31+
"args": [
32+
"--extensionDevelopmentPath=${workspaceFolder}/packages/vscode",
33+
"--disable-extension",
34+
"vscode.typescript-language-features",
35+
"${workspaceFolder}/test-packages"
36+
]
1937
}
2038
]
2139
}

Diff for: CONTRIBUTING.md

+66
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,69 @@ Glint is a family of packages which all live in this repo as a Yarn workspace. T
1717
- Read the project’s [ARCHITECTURE.md](./ARCHITECTURE.md) to understand the basics of how the code base works.
1818

1919
Once you have made changes and added tests to confirm they work correctly, you can then open a PR and we'll work with you to polish it up and get it landed!
20+
21+
# Common Debugging Scenarios
22+
23+
## How to run glint-language-server locally?
24+
25+
If you would like to connect your editor to a locally running version of the Glint language server, first start the `tsc` compiler in watch mode from the root folder of the Glint repo:
26+
27+
```
28+
tsc --build --watch
29+
```
30+
31+
Then you can configure your editor to point to the absolute path of the `./packages/core` folder within this repo when launching the language server. For VSCode users, this means opening your user preferences (after having already installed the Glint VSCode extension) and setting "Glint: Library Path" (aka `glint.libraryPath`) to the absolute path of the `packages/core` folder, e.g. `/Users/machty/code/glint/packages/core`.
32+
33+
With the running `tsc --build --watch` command, the language server will rebuild when any source code files change. _Important_: after any source code file change and subsequent rebuild, you will need to restart the language server from within your editor in order for the changes to be reflected in your editor. In VSCode, this means running "Glint: Restart Glint Server" from the Command Palette.
34+
35+
## How to run glint-language-server locally in debug mode?
36+
37+
There are a few VSCode Launch Configurations within `./vscode/launch.json` that are handy for debugging:
38+
39+
- Both will enable the TS/JS debugger on both the language server and the client-side VSCode extension code, meaning the debug breakpoints will pause execution to allow you to debug things like text completions
40+
- Debug Extension (Glint + TS)
41+
- This spins up a VSCode window with both Glint and the built-in TS language server running.
42+
- In this mode, both language servers will provide duplicate completions and suggestions, which can be useful for testing out feature parity between Glint and TS
43+
- Debug Extension (Glint Only)
44+
- This is useful for testing out the "takeover" mode of running Glint, where Glint is responsible for providing all of the language features (debugging, diagnostics, etc); this is the ideal way to run Glint, but at the time of writing we have not yet achieved feature parity with built-in TS
45+
- By default these extensions will launch the VSCode Extension Host in the `test-packages` subfolder, which have Ember and Glimmerx apps that you can do some basic testing on
46+
- _TIP_: you can open any workspace with the Extension Host, meaning you can even debug the language server with breakpoints on a totally separate Ember repo, for example.
47+
- _NOTE_: debugging takes place within the `glint` workspace, i.e. if you are debugging completions, you'd trigger a completion within the Extension Host, and the breakpoint would pause within the Glint workspace VSCode instance.
48+
49+
These launch configurations can be run via the Run and Debug tab in VSCode.
50+
51+
## How to test out the VSCode extension locally?
52+
53+
Firstly, there is an entire suite of integration tests that will spin up instances of VSCode and test out the VSCode Glint extension. These can be run from the `packages/vscode` directory via:
54+
55+
```
56+
yarn run test
57+
```
58+
59+
Secondly, the Launch Configurations described above (I believe) will run your client-side extension code in debug mode, along with the language server.
60+
61+
## How to see the transformed Intermediate Representation (IR) code of a template
62+
63+
Glint transforms template code into TypeScript code so that it can be type-checked by the vanilla TS compiler. Transformed IR code looks something like:
64+
65+
```ts
66+
static {
67+
({} as typeof import("@glint/environment-ember-loose/-private/dsl")
68+
.templateForBackingValue(this, function(𝚪, χ: typeof import("@glint/environment-ember-loose/-private/dsl")) {
69+
{
70+
const 𝛄 = χ.emitComponent(χ.resolve(χ.Globals["FooComponent"])
71+
({ desc: "notchHeight _ footer", ...χ.NamedArgsMarker }));
72+
𝛄;
73+
{
74+
const [] = 𝛄.blockParams["default"];
75+
{
76+
// ...
77+
```
78+
79+
Sometimes it is useful to see the IR of any .hbs template or .gts/.gjs file for debugging purposes; if you're using VSCode you can see the IR by:
80+
81+
1. Enable "Glint: Debug" in your VSCode user preferences
82+
2. Run the "Glint: Show IR for Debugging" command
83+
84+
Your template code will be replaced by the IR directly in your editor window.
85+

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ Similarly, `glint-language-server` can be used by editor integrations to expose
3939
The language server can also enable your editor to provide other richer help, such as type information on hover, automated refactoring, and more. See [the VS Code extension README](packages/vscode) for further examples.
4040

4141
[using-glint]: https://typed-ember.gitbook.io/glint/getting-started#using-glint
42+
43+
## Debugging Glint
44+
45+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for instructions on how to run and debug the Glint language server and VSCode extension locally.

Diff for: packages/core/__tests__/language-server/completions.test.ts

+135
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,141 @@ describe('Language Server: Completions', () => {
155155
expect(details.detail).toEqual('(property) MyComponent.message: string');
156156
});
157157

158+
test('auto imports', () => {
159+
project.write({
160+
'other.ts': stripIndent`
161+
export let foobar = 123;
162+
`,
163+
'index.ts': stripIndent`
164+
import { thing } from 'nonexistent';
165+
166+
let a = foo
167+
`,
168+
});
169+
170+
const preferences = {
171+
includeCompletionsForModuleExports: true,
172+
allowIncompleteCompletions: true,
173+
};
174+
175+
let server = project.startLanguageServer();
176+
let completions = server.getCompletions(
177+
project.fileURI('index.ts'),
178+
{
179+
line: 2,
180+
character: 11,
181+
},
182+
{},
183+
preferences
184+
);
185+
186+
let importCompletion = completions?.find(
187+
(k) => k.kind == CompletionItemKind.Variable && k.label == 'foobar'
188+
);
189+
190+
let details = server.getCompletionDetails(importCompletion!, {}, preferences);
191+
192+
expect(details.detail).toEqual('Add import from "./other"\n\nlet foobar: number');
193+
194+
expect(details.additionalTextEdits?.length).toEqual(1);
195+
expect(details.additionalTextEdits?.[0].newText).toMatch("import { foobar } from './other';");
196+
expect(details.additionalTextEdits?.[0].range).toEqual({
197+
start: { line: 1, character: 0 },
198+
end: { line: 1, character: 0 },
199+
});
200+
expect(details?.documentation).toEqual({
201+
kind: 'markdown',
202+
value: '',
203+
});
204+
expect(details?.labelDetails?.description).toEqual('./other');
205+
});
206+
207+
test('auto imports with documentation and tags', () => {
208+
project.write({
209+
'other.ts': stripIndent`
210+
/**
211+
* This is a doc comment
212+
* @param foo
213+
*/
214+
export let foobar = 123;
215+
`,
216+
'index.ts': stripIndent`
217+
import { thing } from 'nonexistent';
218+
219+
let a = foo
220+
`,
221+
});
222+
223+
const preferences = {
224+
includeCompletionsForModuleExports: true,
225+
allowIncompleteCompletions: true,
226+
};
227+
228+
let server = project.startLanguageServer();
229+
let completions = server.getCompletions(
230+
project.fileURI('index.ts'),
231+
{
232+
line: 2,
233+
character: 11,
234+
},
235+
{},
236+
preferences
237+
);
238+
239+
let importCompletion = completions?.find(
240+
(k) => k.kind == CompletionItemKind.Variable && k.label == 'foobar'
241+
);
242+
243+
let details = server.getCompletionDetails(importCompletion!, {}, preferences);
244+
245+
expect(details.detail).toEqual('Add import from "./other"\n\nlet foobar: number');
246+
247+
expect(details.additionalTextEdits?.length).toEqual(1);
248+
expect(details.additionalTextEdits?.[0].newText).toMatch("import { foobar } from './other';");
249+
expect(details.additionalTextEdits?.[0].range).toEqual({
250+
start: { line: 1, character: 0 },
251+
end: { line: 1, character: 0 },
252+
});
253+
expect(details?.documentation).toEqual({
254+
kind: 'markdown',
255+
value: 'This is a doc comment\n\n*@param* `foo`',
256+
});
257+
});
258+
259+
test('auto import - import statements - ensure all completions are resolvable', () => {
260+
project.write({
261+
'other.ts': stripIndent`
262+
export let foobar = 123;
263+
`,
264+
'index.ts': stripIndent`
265+
import foo
266+
`,
267+
});
268+
269+
const preferences = {
270+
includeCompletionsForModuleExports: true,
271+
allowIncompleteCompletions: true,
272+
includeCompletionsForImportStatements: true,
273+
includeCompletionsWithInsertText: true, // needs to be present for `includeCompletionsForImportStatements` to work
274+
};
275+
276+
let server = project.startLanguageServer();
277+
let completions = server.getCompletions(
278+
project.fileURI('index.ts'),
279+
{
280+
line: 0,
281+
character: 10,
282+
},
283+
{},
284+
preferences
285+
);
286+
287+
completions?.forEach((completion) => {
288+
let details = server.getCompletionDetails(completion, {}, preferences);
289+
expect(details).toBeTruthy();
290+
});
291+
});
292+
158293
test('referencing own args', async () => {
159294
let code = stripIndent`
160295
import Component, { hbs } from '@glimmerx/component';

0 commit comments

Comments
 (0)