-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
426 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
import type { CompilerOptions } from 'typescript' | ||
import type { HandbookOptions, TwoSlashExecuteOptions, TwoSlashOptions, TwoSlashReturn } from './types' | ||
import { createPositionConverter } from './utils' | ||
|
||
export interface TwoSlashOptionsLegacy extends TwoSlashExecuteOptions { | ||
/** | ||
* @deprecated, use `handbookOptions` instead | ||
*/ | ||
defaultOptions?: Partial<HandbookOptions> | ||
/** | ||
* @deprecated, use `compilerOptions` instead | ||
*/ | ||
defaultCompilerOptions?: CompilerOptions | ||
} | ||
|
||
export interface TwoSlashReturnLegacy { | ||
/** The output code, could be TypeScript, but could also be a JS/JSON/d.ts */ | ||
code: string | ||
|
||
/** The new extension type for the code, potentially changed if they've requested emitted results */ | ||
extension: string | ||
|
||
/** Requests to highlight a particular part of the code */ | ||
highlights: { | ||
kind: 'highlight' | ||
/** The index of the text in the file */ | ||
start: number | ||
/** What line is the highlighted identifier on? */ | ||
line: number | ||
/** At what index in the line does the caret represent */ | ||
offset: number | ||
/** The text of the token which is highlighted */ | ||
text?: string | ||
/** The length of the token */ | ||
length: number | ||
}[] | ||
|
||
/** An array of LSP responses identifiers in the sample */ | ||
staticQuickInfos: { | ||
/** The string content of the node this represents (mainly for debugging) */ | ||
targetString: string | ||
/** The base LSP response (the type) */ | ||
text: string | ||
/** Attached JSDoc info */ | ||
docs: string | undefined | ||
/** The index of the text in the file */ | ||
start: number | ||
/** how long the identifier */ | ||
length: number | ||
/** line number where this is found */ | ||
line: number | ||
/** The character on the line */ | ||
character: number | ||
}[] | ||
|
||
/** Requests to use the LSP to get info for a particular symbol in the source */ | ||
queries: { | ||
kind: 'query' | 'completions' | ||
/** What line is the highlighted identifier on? */ | ||
line: number | ||
/** At what index in the line does the caret represent */ | ||
offset: number | ||
/** The text of the token which is highlighted */ | ||
text?: string | ||
/** Any attached JSDocs */ | ||
docs?: string | undefined | ||
/** The token start which the query indicates */ | ||
start: number | ||
/** The length of the token */ | ||
length: number | ||
/** Results for completions at a particular point */ | ||
completions?: import('typescript').CompletionEntry[] | ||
/* Completion prefix e.g. the letters before the cursor in the word so you can filter */ | ||
completionsPrefix?: string | ||
}[] | ||
|
||
/** The extracted twoslash commands for any custom tags passed in via customTags */ | ||
tags: { | ||
/** What was the name of the tag */ | ||
name: string | ||
/** Where was it located in the original source file */ | ||
line: number | ||
/** What was the text after the `// @tag: ` string (optional because you could do // @tag on it's own line without the ':') */ | ||
annotation?: string | ||
}[] | ||
|
||
/** Diagnostic error messages which came up when creating the program */ | ||
errors: { | ||
renderedMessage: string | ||
id: string | ||
category: 0 | 1 | 2 | 3 | ||
code: number | ||
start: number | undefined | ||
length: number | undefined | ||
line: number | undefined | ||
character: number | undefined | ||
}[] | ||
|
||
/** The URL for this sample in the playground */ | ||
playgroundURL: string | ||
} | ||
|
||
export function convertLegacyOptions<T extends TwoSlashOptionsLegacy>(opts: T): Omit<T, 'defaultOptions' | 'defaultCompilerOptions'> { | ||
return { | ||
...opts, | ||
handbookOptions: opts.handbookOptions || opts.defaultOptions, | ||
compilerOptions: opts.compilerOptions || opts.defaultCompilerOptions, | ||
} | ||
} | ||
|
||
/** | ||
* Covert the new return type to the old one | ||
*/ | ||
export function convertLegacyReturn(result: TwoSlashReturn): TwoSlashReturnLegacy { | ||
return { | ||
code: result.code, | ||
extension: result.meta.extension, | ||
|
||
staticQuickInfos: result.hovers | ||
.map((i): TwoSlashReturnLegacy['staticQuickInfos'][0] => ({ | ||
text: i.text, | ||
docs: i.docs || '', | ||
start: i.start, | ||
length: i.length, | ||
line: i.line, | ||
character: i.character, | ||
targetString: i.target, | ||
})), | ||
|
||
tags: result.tags, | ||
|
||
highlights: result.highlights | ||
.map((h): TwoSlashReturnLegacy['highlights'][0] => ({ | ||
kind: 'highlight', | ||
offset: h.character, | ||
start: h.start, | ||
length: h.length, | ||
line: h.line, | ||
text: h.text, | ||
})), | ||
|
||
queries: ([ | ||
...result.queries | ||
.map((q): TwoSlashReturnLegacy['queries'][0] => ({ | ||
kind: 'query', | ||
docs: q.docs || '', | ||
offset: q.character, | ||
start: q.start, | ||
length: q.length, | ||
line: q.line + 1, | ||
text: q.text, | ||
})), | ||
...result.completions | ||
.map((q): TwoSlashReturnLegacy['queries'][0] => ({ | ||
kind: 'completions', | ||
offset: q.character, | ||
start: q.start, | ||
length: q.length, | ||
line: q.line + 1, | ||
completions: q.completions, | ||
completionsPrefix: q.completionsPrefix, | ||
})), | ||
] as TwoSlashReturnLegacy['queries']) | ||
.sort((a, b) => a.start - b.start), | ||
|
||
errors: result.errors | ||
.map((e): TwoSlashReturnLegacy['errors'][0] => ({ | ||
id: e.id, | ||
code: e.code, | ||
start: e.start, | ||
length: e.length, | ||
line: e.line, | ||
character: e.character, | ||
renderedMessage: e.text, | ||
category: e.level, | ||
})), | ||
|
||
playgroundURL: '', | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import fs from 'node:fs/promises' | ||
import { basename } from 'node:path' | ||
import { twoslasher as twoslasherOriginal } from '@typescript/twoslash' | ||
import { describe, expect, it } from 'vitest' | ||
import { twoslasherLegacy } from '../src' | ||
|
||
describe('legacy', async () => { | ||
await compareCode('./fixtures/examples/cuts_out_unnecessary_code.ts') | ||
await compareCode('./fixtures/examples/errorsWithGenerics.ts') | ||
await compareCode('./fixtures/examples/completions.ts') | ||
|
||
async function compareCode(path: string) { | ||
const code = await fs.readFile(new URL(path, import.meta.url), 'utf-8') | ||
|
||
it(`compare ${basename(path)}`, async () => { | ||
const us = twoslasherLegacy(code, 'ts') | ||
const result = twoslasherOriginal(code, 'ts') | ||
|
||
function cleanup(t: any) { | ||
delete t.playgroundURL | ||
|
||
// We have different calculations for queries, that are not trivial to map back | ||
t.queries.forEach((i: any) => { | ||
delete i.start | ||
delete i.length | ||
delete i.text | ||
delete i.completions | ||
}) | ||
|
||
t.errors.forEach((i: any) => { | ||
delete i.id | ||
}) | ||
|
||
return t | ||
} | ||
|
||
expect( | ||
cleanup(us), | ||
).toStrictEqual( | ||
cleanup(result), | ||
) | ||
}) | ||
} | ||
}) |
Oops, something went wrong.