Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a code fixer for --isolatedDeclarations errors #58260

Merged
merged 15 commits into from Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/compiler/checker.ts
Expand Up @@ -1611,6 +1611,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getBaseTypes,
getBaseTypeOfLiteralType,
getWidenedType,
getWidenedLiteralType,
getTypeFromTypeNode: nodeIn => {
const node = getParseTreeNode(nodeIn, isTypeNode);
return node ? getTypeFromTypeNode(node) : errorType;
Expand Down
40 changes: 40 additions & 0 deletions src/compiler/diagnosticMessages.json
Expand Up @@ -7336,6 +7336,46 @@
"category": "Message",
"code": 90061
},
"Add annotation of type '{0}'": {
"category": "Message",
"code": 90062
},
"Add return type '{0}'": {
"category": "Message",
"code": 90063
},
"Extract base class to variable": {
"category": "Message",
"code": 90064
},
"Extract default export to variable": {
"category": "Message",
"code": 90065
},
"Extract binding expressions to variable": {
"category": "Message",
"code": 90066
},
"Add all missing type annotations": {
"category": "Message",
"code": 90067
},
"Add satisfies and an inline type assertion with '{0}'": {
"category": "Message",
"code": 90068
},
"Extract to variable and replace with '{0} as typeof {0}'": {
"category": "Message",
"code": 90069
},
"Mark array literal as const": {
"category": "Message",
"code": 90070
},
"Annotate types of properties expando function in a namespace": {
"category": "Message",
"code": 90071
},

"Convert function to an ES2015 class": {
"category": "Message",
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Expand Up @@ -5022,6 +5022,8 @@ export interface TypeChecker {
getBaseTypeOfLiteralType(type: Type): Type;
getWidenedType(type: Type): Type;
/** @internal */
getWidenedLiteralType(type: Type): Type;
/** @internal */
getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type | undefined;
/** @internal */
getAwaitedType(type: Type): Type | undefined;
Expand Down
1 change: 1 addition & 0 deletions src/services/_namespaces/ts.codefix.ts
Expand Up @@ -50,6 +50,7 @@ export * from "../codefixes/fixUnreachableCode";
export * from "../codefixes/fixUnusedLabel";
export * from "../codefixes/fixJSDocTypes";
export * from "../codefixes/fixMissingCallParentheses";
export * from "../codefixes/fixMissingTypeAnnotationOnExports";
export * from "../codefixes/fixAwaitInSyncFunction";
export * from "../codefixes/fixPropertyOverrideAccessor";
export * from "../codefixes/inferFromUsage";
Expand Down
9 changes: 8 additions & 1 deletion src/services/codeFixProvider.ts
Expand Up @@ -18,6 +18,7 @@ import {
DiagnosticWithLocation,
FileTextChanges,
flatMap,
getEmitDeclarations,
isString,
map,
TextChange,
Expand Down Expand Up @@ -124,9 +125,15 @@ export function eachDiagnostic(context: CodeFixAllContext, errorCodes: readonly
}

function getDiagnostics({ program, sourceFile, cancellationToken }: CodeFixContextBase) {
return [
const diagnostics = [
jakebailey marked this conversation as resolved.
Show resolved Hide resolved
...program.getSemanticDiagnostics(sourceFile, cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...computeSuggestionDiagnostics(sourceFile, program, cancellationToken),
];
if (getEmitDeclarations(program.getCompilerOptions())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If currently we are supporting providing code fix for errors only when --isolatedDeclarations is turned on may be should get declaration diagnostics only if its on to avoid perf hit

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had them change to this in #58260 (comment), though; in the editor, we'll have already called this for diags, and it's cached.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can flip it back to just isolatedDeclarations if you think it'll be a problem, but it seemed less error prone.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting Jake from the other comment

Actually, now that I think about it, this should probably just be getEmitDeclarations(program.getCompilerOptions()). It's possible that we could have quick fixes for declaration errors that are not in isolated declarations. And this call is cached so should be available for free anyway in codebases with declaration mode enabled.

Would you agree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, my comment was slightly late 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cache does help a little but not whole lot since every edit will have to throw out the errors and recalculate them

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, we call this function already and offer them up as diagnostics in the editor; won't the cost already have been paid?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i forgot about the part where LS.getSemanticDiagnostics gets declaration diagnostics as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for posterity:

    function getSemanticDiagnostics(fileName: string): Diagnostic[] {
        synchronizeHostData();

        const targetSourceFile = getValidSourceFile(fileName);

        // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
        // Therefore only get diagnostics for given file.

        const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
        if (!getEmitDeclarations(program.getCompilerOptions())) {
            return semanticDiagnostics.slice();
        }

        // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
        const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken);
        return [...semanticDiagnostics, ...declarationDiagnostics];
    }

diagnostics.push(
...program.getDeclarationDiagnostics(sourceFile, cancellationToken),
);
}
return diagnostics;
}