diff --git a/.changeset/curly-horses-behave.md b/.changeset/curly-horses-behave.md new file mode 100644 index 00000000..628ec718 --- /dev/null +++ b/.changeset/curly-horses-behave.md @@ -0,0 +1,8 @@ +--- +"@marko/language-server": patch +"@marko/language-tools": patch +"@marko/type-check": patch +"marko-vscode": patch +--- + +Bound values with types diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.html b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.html new file mode 100644 index 00000000..e69de29b diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.md b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.md new file mode 100644 index 00000000..bc2f0ee4 --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.md @@ -0,0 +1,8 @@ +## Hovers +### Ln 1, Col 10 +```marko +> 1 | oneOrTwo/y + | ^ const y: 1 | 2 + 2 | // ^? +``` + diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.ts b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.ts new file mode 100644 index 00000000..7e2f075f --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/index.ts @@ -0,0 +1,60 @@ +export interface Input {} +(function (this: void) { + const input = Marko._.any as Input; + const $signal = Marko._.any as AbortSignal; + const $global = Marko._.getGlobal( + // @ts-expect-error We expect the compiler to error because we are checking if the MarkoRun.Context is defined. + (Marko._.error, Marko._.any as MarkoRun.Context), + ); + const y = Marko._.hoist(() => __marko_internal_hoist__y); + const __marko_internal_tag_1 = Marko._.resolveTemplate( + import("./tags/oneOrTwo.marko"), + ); + { + const y = Marko._.returned(() => __marko_internal_rendered_1); + const __marko_internal_rendered_1 = Marko._.renderTemplate( + __marko_internal_tag_1 /*oneOrTwo*/, + )()()({ + /*oneOrTwo*/ + }); + var __marko_internal_hoist__y = y; + } + Marko._.noop({ y, input, $global, $signal }); + return; +})(); +export default new (class Template extends Marko._.Template<{ + render( + input: Marko.TemplateInput, + stream?: { + write: (chunk: string) => void; + end: (chunk?: string) => void; + }, + ): Marko.Out; + + render( + input: Marko.TemplateInput, + cb?: (err: Error | null, result: Marko.RenderResult) => void, + ): Marko.Out; + + renderSync(input: Marko.TemplateInput): Marko.RenderResult; + + renderToString(input: Marko.TemplateInput): string; + + stream( + input: Marko.TemplateInput, + ): ReadableStream & NodeJS.ReadableStream; + + mount( + input: Marko.TemplateInput, + reference: Node, + position?: "afterbegin" | "afterend" | "beforebegin" | "beforeend", + ): Marko.MountedTemplate; + + api: "tags"; + _(): () => <__marko_internal_input extends unknown>( + input: Marko.Directives & + Input & + Marko._.Relate<__marko_internal_input, Marko.Directives & Input>, + ) => Marko._.ReturnWithScope<__marko_internal_input, void>; +}> {})(); +// ^? diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.html b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.html new file mode 100644 index 00000000..e69de29b diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.md b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.md new file mode 100644 index 00000000..ce702c27 --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.md @@ -0,0 +1,9 @@ +## Hovers +### Ln 2, Col 10 +```marko + 1 | +> 2 | + | ^ const x: number + 3 | // ^? +``` + diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.ts b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.ts new file mode 100644 index 00000000..42c366ff --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/__snapshots__/return-as-type.expected/tags/oneOrTwo.ts @@ -0,0 +1,77 @@ +export interface Input {} +function __marko_internal_template(this: void) { + const input = Marko._.any as Input; + const $signal = Marko._.any as AbortSignal; + const $global = Marko._.getGlobal( + // @ts-expect-error We expect the compiler to error because we are checking if the MarkoRun.Context is defined. + (Marko._.error, Marko._.any as MarkoRun.Context), + ); + const x = Marko._.hoist(() => __marko_internal_hoist__x); + const __marko_internal_tag_1 = Marko._.resolveTemplate( + import("@marko/runtime-tags/tags/let.d.marko"), + ); + { + const x = Marko._.returned(() => __marko_internal_rendered_1); + const __marko_internal_rendered_1 = Marko._.renderTemplate( + __marko_internal_tag_1 /*let*/, + )()()({ + value: 1, + }); + const __marko_internal_change__x = Marko._.change( + "x", + "value", + __marko_internal_rendered_1.return, + ); + var __marko_internal_return = Marko._.returnTag({ + value: x as 1 | 2, + valueChange( + // @ts-ignore + _x, + ) { + __marko_internal_change__x.x = _x; + }, + }); + var __marko_internal_hoist__x = x; + } + Marko._.noop({ x, input, $global, $signal }); + return __marko_internal_return; +} +export default new (class Template extends Marko._.Template<{ + render( + input: Marko.TemplateInput, + stream?: { + write: (chunk: string) => void; + end: (chunk?: string) => void; + }, + ): Marko.Out; + + render( + input: Marko.TemplateInput, + cb?: (err: Error | null, result: Marko.RenderResult) => void, + ): Marko.Out; + + renderSync(input: Marko.TemplateInput): Marko.RenderResult; + + renderToString(input: Marko.TemplateInput): string; + + stream( + input: Marko.TemplateInput, + ): ReadableStream & NodeJS.ReadableStream; + + mount( + input: Marko.TemplateInput, + reference: Node, + position?: "afterbegin" | "afterend" | "beforebegin" | "beforeend", + ): Marko.MountedTemplate; + + api: "tags"; + _(): () => <__marko_internal_input extends unknown>( + input: Marko.Directives & + Input & + Marko._.Relate<__marko_internal_input, Marko.Directives & Input>, + ) => Marko._.ReturnWithScope< + __marko_internal_input, + typeof __marko_internal_template extends () => infer Return ? Return : never + >; +}> {})(); +// ^? diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/index.marko b/packages/language-server/src/__tests__/fixtures/script/return-as-type/index.marko new file mode 100644 index 00000000..efe5008f --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/index.marko @@ -0,0 +1,2 @@ +oneOrTwo/y + // ^? \ No newline at end of file diff --git a/packages/language-server/src/__tests__/fixtures/script/return-as-type/tags/oneOrTwo.marko b/packages/language-server/src/__tests__/fixtures/script/return-as-type/tags/oneOrTwo.marko new file mode 100644 index 00000000..4df57274 --- /dev/null +++ b/packages/language-server/src/__tests__/fixtures/script/return-as-type/tags/oneOrTwo.marko @@ -0,0 +1,3 @@ + + + // ^? \ No newline at end of file diff --git a/packages/language-tools/src/extractors/script/index.ts b/packages/language-tools/src/extractors/script/index.ts index 50a0ed1f..5f8a8c54 100644 --- a/packages/language-tools/src/extractors/script/index.ts +++ b/packages/language-tools/src/extractors/script/index.ts @@ -954,6 +954,7 @@ constructor(_?: Return) {} const valueLiteral = this.#read(boundRange.value); this.#extractor .copy(boundRange.value) + .write(" ") .copy(boundRange.types) .write(`\n)${SEP_COMMA_NEW_LINE}"`) .copy(defaultMapPosition)