All files / src/lsp code_actions.ts

23.95% Statements 23/96
100% Branches 0/0
0% Functions 0/4
23.95% Lines 23/96

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 961x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x 1x                                                                                   1x 1x 1x 1x                                           1x 1x                   1x 1x
import * as LServer from "vscode-languageserver-types";
import {IRegistry} from "../_iregistry";
import {ICodeActionParams} from "./_interfaces";
import {Diagnostics} from "./diagnostics";
import {IEdit} from "../edit_helper";
import {Issue} from "../issue";
import {Position} from "../position";
import {LSPEdit} from "./_edit";
 
export class CodeActions {
  private readonly reg: IRegistry;
 
  public constructor(reg: IRegistry) {
    this.reg = reg;
  }
 
  public find(params: ICodeActionParams): LServer.CodeAction[] {
    const diag = new Diagnostics(this.reg);
    const issues = diag.findIssues(params.textDocument);
    const totals: {[key: string]: number} = {};
    const shown = new Set<string>();

    const ret: LServer.CodeAction[] = [];
    for (const i of issues) {
      const fix = i.getFix();
      if (fix === undefined) {
        continue;
      }

      if (totals[i.getKey()] === undefined) {
        totals[i.getKey()] = 1;
      } else {
        totals[i.getKey()]++;
      }

      if (this.inRange(i, params.range) === false) {
        continue;
      }

      ret.push({
        title: "Apply fix, " + i.getKey(),
        kind: LServer.CodeActionKind.QuickFix,
        diagnostics: [Diagnostics.mapDiagnostic(i)],
        isPreferred: true,
        edit: LSPEdit.mapEdit(fix),
      });
      shown.add(i.getKey());
    }

    for (const s of shown) {
      if (totals[s] > 1) {
        const foo = this.fixAlls(s, issues);
        ret.push(foo);
      }
    }

    return ret;
  }
 
//////////////////////
 
  private fixAlls(key: string, issues: readonly Issue[]): LServer.CodeAction {
    const diagnostics: LServer.Diagnostic[] = [];
    const fixes: IEdit[] = [];

    for (const i of issues) {
      const fix = i.getFix();
      if (fix === undefined) {
        continue;
      }

      fixes.push(fix);
      diagnostics.push(Diagnostics.mapDiagnostic(i));
    }

    return {
      title: "Fix all, " + key,
      kind: LServer.CodeActionKind.QuickFix,
      diagnostics,
      isPreferred: true,
      edit: LSPEdit.mapEdits(fixes),
    };
  }
 
  private inRange(i: Issue, range: LServer.Range): boolean {
    const start = new Position(range.start.line + 1, range.start.character + 1);
    const end = new Position(range.end.line + 1, range.end.character + 1);

    return i.getStart().isBetween(start, end)
      || i.getEnd().isBetween(start, end)
      || start.isBetween(i.getStart(), i.getEnd())
      || end.isBetween(i.getStart(), i.getEnd())
      || end.equals(i.getEnd());
  }
 
}