Files
TypeScript/src/services/types.ts
T
36c87aca8a Private named instance fields (#30829)
* Fix display of private names in language server

Signed-off-by: Joseph Watts <jwatts43@bloomberg.net>
Signed-off-by: Max Heiber <max.heiber@gmail.com>

* Parse private names

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* update parser error recovery tests to use ¬ not #

The intent of the tests seemed to be to
regiment the behavior of the parser
when a weird symbol is encountered.

The `#` is now taken by private identifiers,
so `¬` seems like a good new choice for
keeping the diff small, since it also fits in
16 bits (wide emojis would be treated
as multiple characters, since the scanner
uses ++).

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* Private Name Support in the Checker (#5)

- [x] treat private names as unique:
    - case 1: cannot say that a variable is of a class type unless the variable points to an instance of the class
        - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts)
    - case 2: private names in class hierarchies do not conflict
        - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts)
- [x] `#constructor` is reserved
    - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts)
    - check in `bindWorker`, where every node is visited
- [x] Accessibility modifiers can't be used with private names
    - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts)
    - implemented in `checkAccessibilityModifiers`, using `ModifierFlags.AccessibilityModifier`
- [x] `delete #foo` not allowed
- [x] Private name accesses not allowed outside of the defining class
    - see test: https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts
    - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts)
    - implemented in `checkDeleteExpression`
- [x] Do [the right thing](https://gist.github.com/mheiber/b6fc7adb426c2e1cdaceb5d7786fc630) for nested classes

mv private name tests together

more checker tests for private names

update naming and cleanup for check private names

for private name support in the checker:
- make names more consistent
- remove unnecessary checks
- add utility function to public API
- other small cleanup

Move getPropertyNameForUniqueESSymbol to utility

for consistency with other calculation of
special property names (starting with __),
move the calculation of property names for
unique es symbols to `utilities.ts`.

private name tests strict+es6

Update private name tests to use 'strict'
type checking and to target es6 instead of
default. Makes the js output easier to read
and tests more surface area with other
checker features.

error message for private names in obj literals

Disallow decorating private-named properties
because the spec is still in flux.

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* Add private instance field transformation, pr feedback

Implements private instance fields on top of the class properties refactor.

This commit also includes incorporation of PR feedback on the
checker, parser, and transformer in order to make the rebase
manageable.

Co-Authored-By: Max Heiber <max.heiber@gmail.com>
Co-Authored-By: Ron Buckton <ron.buckton@microsoft.com>

Signed-off-by: Joey Watts <jwatts43@bloomberg.net>
Signed-off-by: Max Heiber <max.heiber@gmail.com>

Incorporate PR feedback

Fix checker crash with new block scoped bindings

Add classExpressionInLoop test

Update baselines for private name errors

Apply suggestions from code review

Fix privateNameFieldCallExpression test

Remove unnecessary comment

Fix PropertyAccessEntityNameExpression type

Remove PrivateName from PropertyNameLiteral

Add createPrivateName

Remove PrivateName type from textSourceNode

Add Debug asserts for invalid syntax kinds

Don't output private name syntax when undeclared

Make PrivateName extend Node

Update baselines for public API

Fix completions in language server

Fix fourslash test crash

intern private name descriptions

undo expensive node.name.parent assignment

Back the way things were on `master`: only
assign node.name.parent when we need to

Add tests for private names and JSDoc

Patch hoverOverPrivateName fourslash test

Fix goToDefinition for private-named fields

remove Debug.fail for private name outside class

Remove Debug.fail in binder.ts::`getDeclarationName`.
It turns out this code path *does* get hit (intentionally).

For best error messages, return `undefined` and rely
on the parser generating a good error message

"Private names are not allowed outside class bodies"

Add rbuckton test cases for private names

These test cases specifically exercise where
we needed to use name-mangling. They are
cases where private names have the same
description.

- private names no conflict when inheriting
- private names distinct even when
the two classes have the same name

check dup instance+static private identifiers

class A {
    #foo;
    static #foo;
}

not allowed because static and private names
share the same lexical scope
https://tc39.es/proposal-class-fields/#prod-ClassBody

refactor getPropertyForPrivateName, rel spans

refactor getPropertyForPrivateName so
it is easier to read (use findAncestor instead
of loop).

Fix bugs in getPropertyForPrivateName:
- make it work with deeply-nested classes with
and without shadowing
- make it catch shadowing when the conflict is
between static and instance
private name descriptions (these can actually
clash)

And add related spans to diagnostics
for getPropertyForPrivateName

catch conflicts between static and instance
private identifiers:
- cannot have an instance and static private identifier
  with the same spelling, as there is only one namespace
  for private names

rename 'PrivateName' to 'PrivateIdentifier'

to match the change of wording in the spec
prposal:

https://tc39.es/proposal-class-fields/#sec-syntax

The rename in the spec was to avoid confusion
between the AST Node PrivateIdentifier
and the internal spec type PrivateName.

So one uses the [[Description]] of a
PrivateIdentifier to look up the PrivateName
for a given scope.

This corresponds closely to our implementation
in the binder and checker:
- we mangle PrivateIdentifier.escapedText to
get a `key` which we use to get the symbol
for a property

f

getLiteralTypeFromProperty-check privateIdentifier

rename and simplify privateNameAndAny test case

make it clearer that all this test is showing is
that we allow accessing arbitrary private identifiers
on `any`.

Note: we could have something more sound here by
checking that there is a private-named field declaration
in a class scope above the property access.

Discussion:
https://github.com/microsoft/TypeScript/pull/30829/files#r302760015

Fix typo in checker

s/identifer/identifier

remove accidental change

patch fourslash test broken by isPrivateIdentifier

just needed to add a check to see if the symbol
.name is defined

extract reportUnmatchedProperty

per @nsandersn feedback

propertiesRelatedTo was getting to long

pull out the unmatchedProperty reporting into
a seprate function

fix typo in private names test

Fix type soundness with private names

Remove PrivateIdentifier from emit with Expr hint

Fixup helpers and set function name for privates

remove accidentally-committed baselines

These baselines somehow ended up in this pr,
though they have nothing to do with the changes

Revert "getLiteralTypeFromProperty-check privateIdentifier"

This reverts commit bd1155c300bc3517a0543580f4790268f86e473f.

reason: the check for isIdentifier in
getLiteralTypeFromProperty is superfluous because
we do this check in getLiteralTypeFromPropertyName

Update comment in private name uniqueness test 3

I think the comments were not accurate and that we
export the error on `this.#x = child.#x` because:
- private names are lexically scoped: the code in question is not in a
lexical scope under the definition of Child's #x.
- private names are private to their containing class: never inherited

This expected behavior matches that of Chrome Canary and
my understanding of the spec

test private names use before def, circular ref

test private names use before def, circular ref

update diagnosticMessages s/delete/'delete'

per @DanielRosenwasser and @sandersn guidance,
use this style in diagnostic messages:

"operand of a 'delete' operator" (single quotes)

rather than old style:

"operand of a delete operator" (single quotes)

This is for consistency, as we use the new
style in the privateIdentifiers error messages
and it is consistent with our messages about
other operators

incorporate private names early exit feedback

and code style change to use a ternary
instead of if so we can 'const'

require private-named fields to be declared in JS

All fields must be declared in TS files.

In JS files, we typically do not have this requirement.

So special-case private fields, which must always
be declared (even in JS files, per spec)

update debug failure for es2015 private identifier

Co-Authored-By: Ron Buckton <ron.buckton@microsoft.com>

fix checker handling of private name in subclasse

update checker and tests to account for the
following ts features:

- private names do not participate in
the prototype chain, but *are* assigned
in the parent class' constructor. So
parent can access its *own* private fields
on instances of the subclass

Add more tests for private-named fields in JS

add test to hit symbolToExpression w private names

symbolToExpression knows about private names
add a test to exercise this code path

ban private-named static methods (not supported yet)

ban private-named methods (not supported yet)

ban private-named accessors (not supported yet)

fix privateIdentifier fourslash test

change assertion throw to return

Co-Authored-By: Ron Buckton <ron.buckton@microsoft.com>

Update comment in checker.ts re reserved members

Remove case for privateIdentifier in EntityNameExpr

Remove case for privateIdentifier in
EntityNameExpr. That code path is never hit,
and privateIdnetifiers cannot be entity names.

remove unnecessary parentheses

Ban private identifier in enum

As the new test, 'privateNameEnumNoEmit',
shows, the checker now correctly makes
a diagnostic for private identifiers in enums.

However, when noEmit is false we
hit this assertion in the transformer.

This assertion will have to be removed
so that we have a diagnostic here instead
of an assertion error.

When the assertion is removed,
the 'privateNameEnum' baseline
will have to be updated

Fix destructuring assignment, use createCallBinding, remove unneeded helper

Add class private field helpers to external helpers

Remove private identifier enum assertion, use missing identifiers

Fix hash map inefficiency by only using get

Update baselines with empty identifier change

Add privateNameEnum test baselines

Fix private identifier destructuring (array assignment defaults, unique names)

Use createPrivateIdentifierAssignment in destructuring transform

Fix lint error

Separate destructuring target visitor from regular visitor

Fix destructuring assignment with this bindings

Fix destructuring assignment with this bindings

Fix syntax error with destructuring assignment output

Disallow private identifiers in property signatures

remove duplicate test baselines

Add tests for undeclarated private identifiers

remove unnecessary cast

Nicer error message for mis-placed hashbang

Workaround v8 bug with destructured assignments

Optimize private identifier stack lookup

Avoid the cost of performing an array lookup to look at the top of the
private identifier environment stack.

Change function name to be more specific

Changes "getOperatorForCompoundAssignment" to
"getNonAssignmentOperatorForCompoundAssignment" now that this
function is accessible to the entire compiler.

Improve test case for private name assignment

Adds a compound assignment test case for a class with private names
being declared on the left-hand-side of the assignment expression.

Remove extra non-private-field test

Remove isPrivateIdentifierAssignmentExpression helper

Don't transform private names in ESNext target

Preserve private fields initialized to functions

Move function expressions to outer scope for efficiency

Add WeakMap collision check

Modify potential WeakMap collision condition

Fix this property assignment binding with private names

Add correct error message for WeakMap collision

Add error for statements before super with private identifiers

Refactor getPropertyForPrivateIdentifier

Add test for private identifier fields initialized to class exprs

Fix shebang errors

Fix private errors on index signatures

Add codefix for missing private property

Update error messages for unsupported private features

Fix inheritance-related errors

Fixes inheritance-related errors with private identifiers by resolving
properties from base classes. Private identifiers do not show up as
properties on a union type, so those do not type-check.

Add test for interface extending class with private access

Remove debugging log

Remove name assignment from private named functions

Rename to getPrivateIdentifierPropertyOfType

Fix index signature test comment

Fix test target syntax error

Change error messages

patch private identifiers outside class bodies

Add test for private identifier with ooo super

Add test for a class with a private identifier
with a non-preambly (for example, not a comment)
statement before 'super':

should error, saying 'super' must come first

Fix nits

incorporate PR feedback

Incorporate checker feedback

- reorganize if statements in checkFunctionOrConstructorSymbol
- remove overload for getPrivateIdentifierPropertyOfType

reorganize if statements in checkFunctionOrConstructorSymbol

test for private names with JSX

use getPropertyOftype in getPropertyForPrivateIdentifier

getPrivateIdentifierPropertyOfType error on synthetic

make getPrivateIdentifierPropertyOfType  error
if given a node that is not from the parse tree

Simplify checkPrivateIdentifierPropertyAccess

use getPropertiesOfType instead of
rehashing that logic

test for private identifiers w decl merging

fix test target for privateNameDeclarationMerging

update baselines

Fix private identifier ++/-- numeric coercion

Remove 'downleveled' from super error

Fix bad comments in helper call emit

Error on private identifiers in JSX tag names

Add more private identifier tests

Add es2015 target for private name destructured binding test

Add privateNameConstructorSignature test

Add test for navigation bar w private identifier

Remove spurious line from test

// in js file
class A {
    exports.#foo = 3; // should error
}

The above line failed to produce an error
when run using the test harness.

When using tsc or the language server,
we got the expected error message.

Removing the troublesome line, as it
seems to say more about the test runner
than about the code it is testing.

Fix inefficient constructor generation

dts: don't emit type for private-identified field

Do not emit types for private-identified fields
when generating declaration files.

// example.ts
export class A {
    #foo: number;
}

// example.d.ts

export declare class A {
    #foo;
}

**This is not ideal!**

The following would be better:

// example.d.ts

export declare unique class A {
    #foo;
}

See discussion:

https://github.com/microsoft/TypeScript/pull/33038#issuecomment-530321165

notice when private-identified field unused

Notice when private-identified fields are unused,
and implement the same behavior as for unused
private-modified fields.

This is used in the language server to make things
grayed out.

This case generates an error when --noUnusedLocals
flag is passed to tsc:
    - "<name> is declared but never used"

accept baselines

Revert "dts: don't emit type for private-identified field"

This reverts commit e50305df5fb88121486291abad14478f5339a455.

Instead of just excluding the type from private identifier
emit, only emit a single private identifier
per class.

This accomplishes nominality while
hiding implementation detail that
is irrelevant to .d.ts consumers

only emit a single private identifier in dts

In dts emit, emit at most one private identifier,
and rename it to `#private`.

refactor getPrivateIdentifierPropertyOfType

- safer check for wehther is parse tree node
- return undefined when not found (instead of
a Debug.fail)

Incorporate PR feedback

Don't rely on parent pointers in transform

Passes context about whether the postfix unary expression value is
discarded down the tree into the visitPostfixUnaryExpression function.

Remove orphaned test baseline files

remove unreachable if

Check `any`-typed private identified fields

Update private identifier incompatible modifier checks

- disallow 'abstract' with private identifiers
- s/private-named-property/private identifier

Add additional call expression test cases

Fix disallow 'abstract' with private identifier

Static private identifiers not inherited

Including this in the PR for private
instance fields even though static
private identifiers are banned.

Reason: this change
improves quality of error messages,
see test case.

Thanks Ron!

Simplifiy private identifier 'any' type handling

Error on private identifier declarations for ES5/ES3

Bind `this` for private identifier property tagged template literals

Fix target for jsdocPrivateName1 test

Update getPrivateIdentifierPropertyOfType API

Make it easier to use by accepting a string
and location, rather than a PrivateIdentifier.

Thanks Ron!

remove orphaned tests

rename test

remove duplicate tests

Remove unrelated error from test

update diagnostic message 'private identifier'

The nodes for hash private fields are now
called 'private identifier'. Update one last
diagnostic message to use the new terminology.

refine solution for static private identifier fields

- use `continue` instead of `filter` for perf
- better naming
- make it clear the current solution will
need to be altered when we lift the ban on
static private identifier fields, including
a test case that should change in the future

Fix display of private identifiers in lang server

Fix bug where private identifiers in completion
tooltips in the playground were showing up
as the symbol table entries (with underscores and such).

https://github.com/microsoft/TypeScript/pull/30829#issuecomment-534157560
Signed-off-by: Max Heiber <max.heiber@gmail.com>

* fix privateIdentifier w !useDefineForClassFields

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* Disallow PrivateIdentifier in Optional Chains

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* restrict privateIdentifier completions correctly

Don't autocomplete privateIdentifiers in
places where they are not allowed.

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* make PrivateIdentifier not a PropertyNameLiteral

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* Added test.

* Accepted baselines.

* Update symbol serializer to understand private fields in JS `.d.ts` emit.

* Accepted baselines.

* fix for private field no initializer esnext

Signed-off-by: Max Heiber <max.heiber@gmail.com>

* fix private fields .d.ts emit for JS w expando

fix bug where the following in a JS file
would lead to a `#private` in the .d.ts:

```js
class C {
    constructor () {
        this.a = 3
    }
}
```

Co-authored-by: Joey Watts <joey.watts.96@gmail.com>
Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
2019-12-27 13:07:35 -08:00

1326 lines
52 KiB
TypeScript

namespace ts {
export interface Node {
getSourceFile(): SourceFile;
getChildCount(sourceFile?: SourceFile): number;
getChildAt(index: number, sourceFile?: SourceFile): Node;
getChildren(sourceFile?: SourceFile): Node[];
/* @internal */
getChildren(sourceFile?: SourceFileLike): Node[]; // eslint-disable-line @typescript-eslint/unified-signatures
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
/* @internal */
getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number; // eslint-disable-line @typescript-eslint/unified-signatures
getFullStart(): number;
getEnd(): number;
getWidth(sourceFile?: SourceFileLike): number;
getFullWidth(): number;
getLeadingTriviaWidth(sourceFile?: SourceFile): number;
getFullText(sourceFile?: SourceFile): string;
getText(sourceFile?: SourceFile): string;
getFirstToken(sourceFile?: SourceFile): Node | undefined;
/* @internal */
getFirstToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
getLastToken(sourceFile?: SourceFile): Node | undefined;
/* @internal */
getLastToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
// See ts.forEachChild for documentation.
forEachChild<T>(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined;
}
export interface Identifier {
readonly text: string;
}
export interface PrivateIdentifier {
readonly text: string;
}
export interface Symbol {
readonly name: string;
getFlags(): SymbolFlags;
getEscapedName(): __String;
getName(): string;
getDeclarations(): Declaration[] | undefined;
getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[];
getJsDocTags(): JSDocTagInfo[];
}
export interface Type {
getFlags(): TypeFlags;
getSymbol(): Symbol | undefined;
getProperties(): Symbol[];
getProperty(propertyName: string): Symbol | undefined;
getApparentProperties(): Symbol[];
getCallSignatures(): readonly Signature[];
getConstructSignatures(): readonly Signature[];
getStringIndexType(): Type | undefined;
getNumberIndexType(): Type | undefined;
getBaseTypes(): BaseType[] | undefined;
getNonNullableType(): Type;
/*@internal*/ getNonOptionalType(): Type;
/*@internal*/ isNullableType(): boolean;
getConstraint(): Type | undefined;
getDefault(): Type | undefined;
isUnion(): this is UnionType;
isIntersection(): this is IntersectionType;
isUnionOrIntersection(): this is UnionOrIntersectionType;
isLiteral(): this is LiteralType;
isStringLiteral(): this is StringLiteralType;
isNumberLiteral(): this is NumberLiteralType;
isTypeParameter(): this is TypeParameter;
isClassOrInterface(): this is InterfaceType;
isClass(): this is InterfaceType;
}
export interface TypeReference {
typeArguments?: readonly Type[];
}
export interface Signature {
getDeclaration(): SignatureDeclaration;
getTypeParameters(): TypeParameter[] | undefined;
getParameters(): Symbol[];
getReturnType(): Type;
getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[];
getJsDocTags(): JSDocTagInfo[];
}
export interface SourceFile {
/* @internal */ version: string;
/* @internal */ scriptSnapshot: IScriptSnapshot | undefined;
/* @internal */ nameTable: UnderscoreEscapedMap<number> | undefined;
/* @internal */ getNamedDeclarations(): Map<readonly Declaration[]>;
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineEndOfPosition(pos: number): number;
getLineStarts(): readonly number[];
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
/* @internal */ sourceMapper?: DocumentPositionMapper;
}
export interface SourceFileLike {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
}
export interface SourceMapSource {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
}
/**
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
* the same values.
*/
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface IScriptSnapshot {
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
/** Gets the length of this script snapshot. */
getLength(): number;
/**
* Gets the TextChangeRange that describe how the text changed between this text and
* an older version. This information is used by the incremental parser to determine
* what sections of the script need to be re-parsed. 'undefined' can be returned if the
* change range cannot be determined. However, in that case, incremental parsing will
* not happen and the entire document will be re - parsed.
*/
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined;
/** Releases all resources held by this script snapshot */
dispose?(): void;
}
export namespace ScriptSnapshot {
class StringScriptSnapshot implements IScriptSnapshot {
constructor(private text: string) {
}
public getText(start: number, end: number): string {
return start === 0 && end === this.text.length
? this.text
: this.text.substring(start, end);
}
public getLength(): number {
return this.text.length;
}
public getChangeRange(): TextChangeRange | undefined {
// Text-based snapshots do not support incremental parsing. Return undefined
// to signal that to the caller.
return undefined;
}
}
export function fromString(text: string): IScriptSnapshot {
return new StringScriptSnapshot(text);
}
}
export interface PreProcessedFileInfo {
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
libReferenceDirectives: FileReference[];
importedFiles: FileReference[];
ambientExternalModules?: string[];
isLibFile: boolean;
}
export interface HostCancellationToken {
isCancellationRequested(): boolean;
}
export interface InstallPackageOptions {
fileName: Path;
packageName: string;
}
/* @internal */
export const enum PackageJsonDependencyGroup {
Dependencies = 1 << 0,
DevDependencies = 1 << 1,
PeerDependencies = 1 << 2,
OptionalDependencies = 1 << 3,
All = Dependencies | DevDependencies | PeerDependencies | OptionalDependencies,
}
/* @internal */
export interface PackageJsonInfo {
fileName: string;
dependencies?: Map<string>;
devDependencies?: Map<string>;
peerDependencies?: Map<string>;
optionalDependencies?: Map<string>;
get(dependencyName: string, inGroups?: PackageJsonDependencyGroup): string | undefined;
has(dependencyName: string, inGroups?: PackageJsonDependencyGroup): boolean;
}
//
// Public interface of the host of a language service instance.
//
export interface LanguageServiceHost extends ModuleSpecifierResolutionHost {
getCompilationSettings(): CompilerOptions;
getNewLine?(): string;
getProjectVersion?(): string;
getScriptFileNames(): string[];
getScriptKind?(fileName: string): ScriptKind;
getScriptVersion(fileName: string): string;
getScriptSnapshot(fileName: string): IScriptSnapshot | undefined;
getProjectReferences?(): readonly ProjectReference[] | undefined;
getLocalizedDiagnosticMessages?(): any;
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
getDefaultLibFileName(options: CompilerOptions): string;
log?(s: string): void;
trace?(s: string): void;
error?(s: string): void;
/*
* LS host can optionally implement these methods to support completions for module specifiers.
* Without these methods, only completions for ambient modules will be provided.
*/
readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
readFile?(path: string, encoding?: string): string | undefined;
realpath?(path: string): string;
fileExists?(path: string): boolean;
/*
* LS host can optionally implement these methods to support automatic updating when new type libraries are installed
*/
getTypeRootsVersion?(): number;
/*
* LS host can optionally implement this method if it wants to be completely in charge of module name resolution.
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
* host specific questions using 'getScriptSnapshot'.
*
* If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too.
*/
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
/* @internal */
getGlobalTypingsCacheLocation?(): string | undefined;
/*
* Required for full import and type reference completions.
* These should be unprefixed names. E.g. `getDirectories("/foo/bar")` should return `["a", "b"]`, not `["/foo/bar/a", "/foo/bar/b"]`.
*/
getDirectories?(directoryName: string): string[];
/**
* Gets a set of custom transformers to use during emit.
*/
getCustomTransformers?(): CustomTransformers | undefined;
isKnownTypesPackageName?(name: string): boolean;
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
writeFile?(fileName: string, content: string): void;
/* @internal */
getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined;
/* @internal */
getSourceFileLike?(fileName: string): SourceFileLike | undefined;
/* @internal */
getPackageJsonsVisibleToFile?(fileName: string, rootDir?: string): readonly PackageJsonInfo[];
/* @internal */
getImportSuggestionsCache?(): Completions.ImportSuggestionsForFileCache;
/* @internal */
setResolvedProjectReferenceCallbacks?(callbacks: ResolvedProjectReferenceCallbacks): void;
/* @internal */
useSourceOfProjectReferenceRedirect?(): boolean;
}
/* @internal */
export const emptyOptions = {};
export type WithMetadata<T> = T & { metadata?: unknown; };
//
// Public services of a language service instance associated
// with a language service host instance
//
export interface LanguageService {
cleanupSemanticCache(): void;
getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[];
/** The first time this is called, it will return global diagnostics (no location). */
getSemanticDiagnostics(fileName: string): Diagnostic[];
getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[];
// TODO: Rename this to getProgramDiagnostics to better indicate that these are any
// diagnostics present for the program level, and not just 'options' diagnostics.
getCompilerOptionsDiagnostics(): Diagnostic[];
/**
* @deprecated Use getEncodedSyntacticClassifications instead.
*/
getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
/**
* @deprecated Use getEncodedSemanticClassifications instead.
*/
getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
// Encoded as triples of [start, length, ClassificationType].
getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications;
getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications;
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): WithMetadata<CompletionInfo> | undefined;
// "options" and "source" are optional only for backwards-compatibility
getCompletionEntryDetails(
fileName: string,
position: number,
name: string,
formatOptions: FormatCodeOptions | FormatCodeSettings | undefined,
source: string | undefined,
preferences: UserPreferences | undefined,
): CompletionEntryDetails | undefined;
getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined;
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined;
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined;
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined;
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined;
getImplementationAtPosition(fileName: string, position: number): readonly ImplementationLocation[] | undefined;
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined;
findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined;
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined;
/** @deprecated */
getOccurrencesAtPosition(fileName: string, position: number): readonly ReferenceEntry[] | undefined;
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[];
getNavigationBarItems(fileName: string): NavigationBarItem[];
getNavigationTree(fileName: string): NavigationTree;
prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined;
provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[];
provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[];
getOutliningSpans(fileName: string): OutliningSpan[];
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number;
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
/**
* This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag.
* Editors should call this after `>` is typed.
*/
getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined;
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined;
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
/** @internal */
getSourceMapper(): SourceMapper;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[];
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput;
getProgram(): Program | undefined;
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
dispose(): void;
}
export interface JsxClosingTagInfo {
readonly newText: string;
}
export interface CombinedCodeFixScope { type: "file"; fileName: string; }
export type OrganizeImportsScope = CombinedCodeFixScope;
export type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<";
export interface GetCompletionsAtPositionOptions extends UserPreferences {
/**
* If the editor is asking for completions because a certain character was typed
* (as opposed to when the user explicitly requested them) this should be set.
*/
triggerCharacter?: CompletionsTriggerCharacter;
/** @deprecated Use includeCompletionsForModuleExports */
includeExternalModuleExports?: boolean;
/** @deprecated Use includeCompletionsWithInsertText */
includeInsertTextCompletions?: boolean;
}
export type SignatureHelpTriggerCharacter = "," | "(" | "<";
export type SignatureHelpRetriggerCharacter = SignatureHelpTriggerCharacter | ")";
export interface SignatureHelpItemsOptions {
triggerReason?: SignatureHelpTriggerReason;
}
export type SignatureHelpTriggerReason =
| SignatureHelpInvokedReason
| SignatureHelpCharacterTypedReason
| SignatureHelpRetriggeredReason;
/**
* Signals that the user manually requested signature help.
* The language service will unconditionally attempt to provide a result.
*/
export interface SignatureHelpInvokedReason {
kind: "invoked";
triggerCharacter?: undefined;
}
/**
* Signals that the signature help request came from a user typing a character.
* Depending on the character and the syntactic context, the request may or may not be served a result.
*/
export interface SignatureHelpCharacterTypedReason {
kind: "characterTyped";
/**
* Character that was responsible for triggering signature help.
*/
triggerCharacter: SignatureHelpTriggerCharacter;
}
/**
* Signals that this signature help request came from typing a character or moving the cursor.
* This should only occur if a signature help session was already active and the editor needs to see if it should adjust.
* The language service will unconditionally attempt to provide a result.
* `triggerCharacter` can be `undefined` for a retrigger caused by a cursor move.
*/
export interface SignatureHelpRetriggeredReason {
kind: "retrigger";
/**
* Character that was responsible for triggering signature help.
*/
triggerCharacter?: SignatureHelpRetriggerCharacter;
}
export interface ApplyCodeActionCommandResult {
successMessage: string;
}
export interface Classifications {
spans: number[];
endOfLineState: EndOfLineState;
}
export interface ClassifiedSpan {
textSpan: TextSpan;
classificationType: ClassificationTypeNames;
}
/**
* Navigation bar interface designed for visual studio's dual-column layout.
* This does not form a proper tree.
* The navbar is returned as a list of top-level items, each of which has a list of child items.
* Child items always have an empty array for their `childItems`.
*/
export interface NavigationBarItem {
text: string;
kind: ScriptElementKind;
kindModifiers: string;
spans: TextSpan[];
childItems: NavigationBarItem[];
indent: number;
bolded: boolean;
grayed: boolean;
}
/**
* Node in a tree of nested declarations in a file.
* The top node is always a script or module node.
*/
export interface NavigationTree {
/** Name of the declaration, or a short description, e.g. "<class>". */
text: string;
kind: ScriptElementKind;
/** ScriptElementKindModifier separated by commas, e.g. "public,abstract" */
kindModifiers: string;
/**
* Spans of the nodes that generated this declaration.
* There will be more than one if this is the result of merging.
*/
spans: TextSpan[];
nameSpan: TextSpan | undefined;
/** Present if non-empty */
childItems?: NavigationTree[];
}
export interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
file: string;
span: TextSpan;
selectionSpan: TextSpan;
}
export interface CallHierarchyIncomingCall {
from: CallHierarchyItem;
fromSpans: TextSpan[];
}
export interface CallHierarchyOutgoingCall {
to: CallHierarchyItem;
fromSpans: TextSpan[];
}
export interface TodoCommentDescriptor {
text: string;
priority: number;
}
export interface TodoComment {
descriptor: TodoCommentDescriptor;
message: string;
position: number;
}
export interface TextChange {
span: TextSpan;
newText: string;
}
export interface FileTextChanges {
fileName: string;
textChanges: readonly TextChange[];
isNewFile?: boolean;
}
export interface CodeAction {
/** Description of the code action to display in the UI of the editor */
description: string;
/** Text changes to apply to each file as part of the code action */
changes: FileTextChanges[];
/**
* If the user accepts the code fix, the editor should send the action back in a `applyAction` request.
* This allows the language service to have side effects (e.g. installing dependencies) upon a code fix.
*/
commands?: CodeActionCommand[];
}
export interface CodeFixAction extends CodeAction {
/** Short name to identify the fix, for use by telemetry. */
fixName: string;
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
* This may be omitted to indicate that the code fix can't be applied in a group.
*/
fixId?: {};
fixAllDescription?: string;
}
export interface CombinedCodeActions {
changes: readonly FileTextChanges[];
commands?: readonly CodeActionCommand[];
}
// Publicly, this type is just `{}`. Internally it is a union of all the actions we use.
// See `commands?: {}[]` in protocol.ts
export type CodeActionCommand = InstallPackageAction;
export interface InstallPackageAction {
/* @internal */ readonly type: "install package";
/* @internal */ readonly file: string;
/* @internal */ readonly packageName: string;
}
/**
* A set of one or more available refactoring actions, grouped under a parent refactoring.
*/
export interface ApplicableRefactorInfo {
/**
* The programmatic name of the refactoring
*/
name: string;
/**
* A description of this refactoring category to show to the user.
* If the refactoring gets inlined (see below), this text will not be visible.
*/
description: string;
/**
* Inlineable refactorings can have their actions hoisted out to the top level
* of a context menu. Non-inlineanable refactorings should always be shown inside
* their parent grouping.
*
* If not specified, this value is assumed to be 'true'
*/
inlineable?: boolean;
actions: RefactorActionInfo[];
}
/**
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
* offer several actions, each corresponding to a surround class or closure to extract into.
*/
export interface RefactorActionInfo {
/**
* The programmatic name of the refactoring action
*/
name: string;
/**
* A description of this refactoring action to show to the user.
* If the parent refactoring is inlined away, this will be the only text shown,
* so this description should make sense by itself if the parent is inlineable=true
*/
description: string;
}
/**
* A set of edits to make in response to a refactor action, plus an optional
* location where renaming should be invoked from
*/
export interface RefactorEditInfo {
edits: FileTextChanges[];
renameFilename?: string ;
renameLocation?: number;
commands?: CodeActionCommand[];
}
export interface TextInsertion {
newText: string;
/** The position in newText the caret should point to after the insertion. */
caretOffset: number;
}
export interface DocumentSpan {
textSpan: TextSpan;
fileName: string;
/**
* If the span represents a location that was remapped (e.g. via a .d.ts.map file),
* then the original filename and span will be specified here
*/
originalTextSpan?: TextSpan;
originalFileName?: string;
/**
* If DocumentSpan.textSpan is the span for name of the declaration,
* then this is the span for relevant declaration
*/
contextSpan?: TextSpan;
originalContextSpan?: TextSpan;
}
export interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
export interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
isDefinition: boolean;
isInString?: true;
}
export interface ImplementationLocation extends DocumentSpan {
kind: ScriptElementKind;
displayParts: SymbolDisplayPart[];
}
export const enum HighlightSpanKind {
none = "none",
definition = "definition",
reference = "reference",
writtenReference = "writtenReference",
}
export interface HighlightSpan {
fileName?: string;
isInString?: true;
textSpan: TextSpan;
contextSpan?: TextSpan;
kind: HighlightSpanKind;
}
export interface NavigateToItem {
name: string;
kind: ScriptElementKind;
kindModifiers: string;
matchKind: "exact" | "prefix" | "substring" | "camelCase";
isCaseSensitive: boolean;
fileName: string;
textSpan: TextSpan;
containerName: string;
containerKind: ScriptElementKind;
}
export enum IndentStyle {
None = 0,
Block = 1,
Smart = 2,
}
export enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove",
}
/* @deprecated - consider using EditorSettings instead */
export interface EditorOptions {
BaseIndentSize?: number;
IndentSize: number;
TabSize: number;
NewLineCharacter: string;
ConvertTabsToSpaces: boolean;
IndentStyle: IndentStyle;
}
// TODO: GH#18217 These are frequently asserted as defined
export interface EditorSettings {
baseIndentSize?: number;
indentSize?: number;
tabSize?: number;
newLineCharacter?: string;
convertTabsToSpaces?: boolean;
indentStyle?: IndentStyle;
}
/* @deprecated - consider using FormatCodeSettings instead */
export interface FormatCodeOptions extends EditorOptions {
InsertSpaceAfterCommaDelimiter: boolean;
InsertSpaceAfterSemicolonInForStatements: boolean;
InsertSpaceBeforeAndAfterBinaryOperators: boolean;
InsertSpaceAfterConstructor?: boolean;
InsertSpaceAfterKeywordsInControlFlowStatements: boolean;
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
InsertSpaceAfterTypeAssertion?: boolean;
InsertSpaceBeforeFunctionParenthesis?: boolean;
PlaceOpenBraceOnNewLineForFunctions: boolean;
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
insertSpaceBeforeTypeAnnotation?: boolean;
}
export interface FormatCodeSettings extends EditorSettings {
readonly insertSpaceAfterCommaDelimiter?: boolean;
readonly insertSpaceAfterSemicolonInForStatements?: boolean;
readonly insertSpaceBeforeAndAfterBinaryOperators?: boolean;
readonly insertSpaceAfterConstructor?: boolean;
readonly insertSpaceAfterKeywordsInControlFlowStatements?: boolean;
readonly insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
readonly insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
readonly insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
readonly insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
readonly insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
readonly insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
readonly insertSpaceAfterTypeAssertion?: boolean;
readonly insertSpaceBeforeFunctionParenthesis?: boolean;
readonly placeOpenBraceOnNewLineForFunctions?: boolean;
readonly placeOpenBraceOnNewLineForControlBlocks?: boolean;
readonly insertSpaceBeforeTypeAnnotation?: boolean;
readonly indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
readonly semicolons?: SemicolonPreference;
}
export function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings {
return {
indentSize: 4,
tabSize: 4,
newLineCharacter: newLineCharacter || "\n",
convertTabsToSpaces: true,
indentStyle: IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
semicolons: SemicolonPreference.Ignore,
};
}
/* @internal */
export const testFormatSettings = getDefaultFormatCodeSettings("\n");
export interface DefinitionInfo extends DocumentSpan {
kind: ScriptElementKind;
name: string;
containerKind: ScriptElementKind;
containerName: string;
/* @internal */ isLocal?: boolean;
}
export interface DefinitionInfoAndBoundSpan {
definitions?: readonly DefinitionInfo[];
textSpan: TextSpan;
}
export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo {
displayParts: SymbolDisplayPart[];
}
export interface ReferencedSymbol {
definition: ReferencedSymbolDefinitionInfo;
references: ReferenceEntry[];
}
export enum SymbolDisplayPartKind {
aliasName,
className,
enumName,
fieldName,
interfaceName,
keyword,
lineBreak,
numericLiteral,
stringLiteral,
localName,
methodName,
moduleName,
operator,
parameterName,
propertyName,
punctuation,
space,
text,
typeParameterName,
enumMemberName,
functionName,
regularExpressionLiteral,
}
export interface SymbolDisplayPart {
text: string;
kind: string;
}
export interface JSDocTagInfo {
name: string;
text?: string;
}
export interface QuickInfo {
kind: ScriptElementKind;
kindModifiers: string;
textSpan: TextSpan;
displayParts?: SymbolDisplayPart[];
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
export type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
export interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
export interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
export interface RenameInfoOptions {
readonly allowRenameOfImportPath?: boolean;
}
export interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
displayParts: SymbolDisplayPart[];
isOptional: boolean;
}
export interface SelectionRange {
textSpan: TextSpan;
parent?: SelectionRange;
}
/**
* Represents a single signature to show in signature help.
* The id is used for subsequent calls into the language service to ask questions about the
* signature help item in the context of any documents that have been updated. i.e. after
* an edit has happened, while signature help is still active, the host can ask important
* questions like 'what parameter is the user currently contained within?'.
*/
export interface SignatureHelpItem {
isVariadic: boolean;
prefixDisplayParts: SymbolDisplayPart[];
suffixDisplayParts: SymbolDisplayPart[];
separatorDisplayParts: SymbolDisplayPart[];
parameters: SignatureHelpParameter[];
documentation: SymbolDisplayPart[];
tags: JSDocTagInfo[];
}
/**
* Represents a set of signature help items, and the preferred item that should be selected.
*/
export interface SignatureHelpItems {
items: SignatureHelpItem[];
applicableSpan: TextSpan;
selectedItemIndex: number;
argumentIndex: number;
argumentCount: number;
}
export interface CompletionInfo {
/** Not true for all global completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */
isGlobalCompletion: boolean;
isMemberCompletion: boolean;
/**
* true when the current location also allows for a new identifier
*/
isNewIdentifierLocation: boolean;
entries: CompletionEntry[];
}
// see comments in protocol.ts
export interface CompletionEntry {
name: string;
kind: ScriptElementKind;
kindModifiers?: string; // see ScriptElementKindModifier, comma separated
sortText: string;
insertText?: string;
/**
* An optional span that indicates the text to be replaced by this completion item.
* If present, this span should be used instead of the default one.
* It will be set if the required span differs from the one generated by the default replacement behavior.
*/
replacementSpan?: TextSpan;
hasAction?: true;
source?: string;
isRecommended?: true;
}
export interface CompletionEntryDetails {
name: string;
kind: ScriptElementKind;
kindModifiers: string; // see ScriptElementKindModifier, comma separated
displayParts: SymbolDisplayPart[];
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
codeActions?: CodeAction[];
source?: SymbolDisplayPart[];
}
export interface OutliningSpan {
/** The span of the document to actually collapse. */
textSpan: TextSpan;
/** The span of the document to display when the user hovers over the collapsed span. */
hintSpan: TextSpan;
/** The text to display in the editor for the collapsed region. */
bannerText: string;
/**
* Whether or not this region should be automatically collapsed when
* the 'Collapse to Definitions' command is invoked.
*/
autoCollapse: boolean;
/**
* Classification of the contents of the span
*/
kind: OutliningSpanKind;
}
export const enum OutliningSpanKind {
/** Single or multi-line comments */
Comment = "comment",
/** Sections marked by '// #region' and '// #endregion' comments */
Region = "region",
/** Declarations and expressions */
Code = "code",
/** Contiguous blocks of import declarations */
Imports = "imports"
}
export const enum OutputFileType {
JavaScript,
SourceMap,
Declaration
}
export const enum EndOfLineState {
None,
InMultiLineCommentTrivia,
InSingleQuoteStringLiteral,
InDoubleQuoteStringLiteral,
InTemplateHeadOrNoSubstitutionTemplate,
InTemplateMiddleOrTail,
InTemplateSubstitutionPosition,
}
export enum TokenClass {
Punctuation,
Keyword,
Operator,
Comment,
Whitespace,
Identifier,
NumberLiteral,
BigIntLiteral,
StringLiteral,
RegExpLiteral,
}
export interface ClassificationResult {
finalLexState: EndOfLineState;
entries: ClassificationInfo[];
}
export interface ClassificationInfo {
length: number;
classification: TokenClass;
}
export interface Classifier {
/**
* Gives lexical classifications of tokens on a line without any syntactic context.
* For instance, a token consisting of the text 'string' can be either an identifier
* named 'string' or the keyword 'string', however, because this classifier is not aware,
* it relies on certain heuristics to give acceptable results. For classifications where
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
* lexical, syntactic, and semantic classifiers may issue the best user experience.
*
* @param text The text of a line to classify.
* @param lexState The state of the lexical classifier at the end of the previous line.
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
* certain heuristics may be used in its place; however, if there is a
* syntactic classifier (syntacticClassifierAbsent=false), certain
* classifications which may be incorrectly categorized will be given
* back as Identifiers in order to allow the syntactic classifier to
* subsume the classification.
* @deprecated Use getLexicalClassifications instead.
*/
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications;
}
export const enum ScriptElementKind {
unknown = "",
warning = "warning",
/** predefined type (void) or keyword (class) */
keyword = "keyword",
/** top level script node */
scriptElement = "script",
/** module foo {} */
moduleElement = "module",
/** class X {} */
classElement = "class",
/** var x = class X {} */
localClassElement = "local class",
/** interface Y {} */
interfaceElement = "interface",
/** type T = ... */
typeElement = "type",
/** enum E */
enumElement = "enum",
enumMemberElement = "enum member",
/**
* Inside module and script only
* const v = ..
*/
variableElement = "var",
/** Inside function */
localVariableElement = "local var",
/**
* Inside module and script only
* function f() { }
*/
functionElement = "function",
/** Inside function */
localFunctionElement = "local function",
/** class X { [public|private]* foo() {} } */
memberFunctionElement = "method",
/** class X { [public|private]* [get|set] foo:number; } */
memberGetAccessorElement = "getter",
memberSetAccessorElement = "setter",
/**
* class X { [public|private]* foo:number; }
* interface Y { foo:number; }
*/
memberVariableElement = "property",
/** class X { constructor() { } } */
constructorImplementationElement = "constructor",
/** interface Y { ():number; } */
callSignatureElement = "call",
/** interface Y { []:number; } */
indexSignatureElement = "index",
/** interface Y { new():Y; } */
constructSignatureElement = "construct",
/** function foo(*Y*: string) */
parameterElement = "parameter",
typeParameterElement = "type parameter",
primitiveType = "primitive type",
label = "label",
alias = "alias",
constElement = "const",
letElement = "let",
directory = "directory",
externalModuleName = "external module name",
/**
* <JsxTagName attribute1 attribute2={0} />
*/
jsxAttribute = "JSX attribute",
/** String literal */
string = "string",
}
export const enum ScriptElementKindModifier {
none = "",
publicMemberModifier = "public",
privateMemberModifier = "private",
protectedMemberModifier = "protected",
exportedModifier = "export",
ambientModifier = "declare",
staticModifier = "static",
abstractModifier = "abstract",
optionalModifier = "optional",
dtsModifier = ".d.ts",
tsModifier = ".ts",
tsxModifier = ".tsx",
jsModifier = ".js",
jsxModifier = ".jsx",
jsonModifier = ".json",
}
export const enum ClassificationTypeNames {
comment = "comment",
identifier = "identifier",
keyword = "keyword",
numericLiteral = "number",
bigintLiteral = "bigint",
operator = "operator",
stringLiteral = "string",
whiteSpace = "whitespace",
text = "text",
punctuation = "punctuation",
className = "class name",
enumName = "enum name",
interfaceName = "interface name",
moduleName = "module name",
typeParameterName = "type parameter name",
typeAliasName = "type alias name",
parameterName = "parameter name",
docCommentTagName = "doc comment tag name",
jsxOpenTagName = "jsx open tag name",
jsxCloseTagName = "jsx close tag name",
jsxSelfClosingTagName = "jsx self closing tag name",
jsxAttribute = "jsx attribute",
jsxText = "jsx text",
jsxAttributeStringLiteralValue = "jsx attribute string literal value",
}
export const enum ClassificationType {
comment = 1,
identifier = 2,
keyword = 3,
numericLiteral = 4,
operator = 5,
stringLiteral = 6,
regularExpressionLiteral = 7,
whiteSpace = 8,
text = 9,
punctuation = 10,
className = 11,
enumName = 12,
interfaceName = 13,
moduleName = 14,
typeParameterName = 15,
typeAliasName = 16,
parameterName = 17,
docCommentTagName = 18,
jsxOpenTagName = 19,
jsxCloseTagName = 20,
jsxSelfClosingTagName = 21,
jsxAttribute = 22,
jsxText = 23,
jsxAttributeStringLiteralValue = 24,
bigintLiteral = 25,
}
/** @internal */
export interface CodeFixRegistration {
errorCodes: readonly number[];
getCodeActions(context: CodeFixContext): CodeFixAction[] | undefined;
fixIds?: readonly string[];
getAllCodeActions?(context: CodeFixAllContext): CombinedCodeActions;
}
/** @internal */
export interface CodeFixContextBase extends textChanges.TextChangesContext {
sourceFile: SourceFile;
program: Program;
cancellationToken: CancellationToken;
preferences: UserPreferences;
}
/** @internal */
export interface CodeFixAllContext extends CodeFixContextBase {
fixId: {};
}
/** @internal */
export interface CodeFixContext extends CodeFixContextBase {
errorCode: number;
span: TextSpan;
}
/** @internal */
export interface Refactor {
/** Compute the associated code actions */
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
/** Compute (quickly) which actions are available here */
getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[];
}
/** @internal */
export interface RefactorContext extends textChanges.TextChangesContext {
file: SourceFile;
startPosition: number;
endPosition?: number;
program: Program;
cancellationToken?: CancellationToken;
preferences: UserPreferences;
}
}