vscode#CodeActionContext TypeScript Examples

The following examples show how to use vscode#CodeActionContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: codeActionProvider.ts    From dendron with GNU Affero General Public License v3.0 6 votes vote down vote up
doctorFrontmatterProvider: CodeActionProvider = {
  provideCodeActions: sentryReportingCallback(
    (
      _document: TextDocument,
      _range: Range | Selection,
      context: CodeActionContext,
      _token: CancellationToken
    ) => {
      // No-op if we're not in a Dendron Workspace
      if (!DendronExtension.isActive()) {
        return;
      }
      // Only provide fix frontmatter action if the diagnostic is correct
      const diagnostics = context.diagnostics.filter(
        (item) => item.code === BAD_FRONTMATTER_CODE
      );
      if (diagnostics.length !== 0) {
        const action: CodeAction = {
          title: "Fix the frontmatter",
          diagnostics,
          isPreferred: true,
          kind: CodeActionKind.QuickFix,
          command: {
            command: new DoctorCommand(ExtensionProvider.getExtension()).key,
            title: "Fix the frontmatter",
            arguments: [
              { scope: "file", action: DoctorActionsEnum.FIX_FRONTMATTER },
            ],
          },
        };
        return [action];
      }
      return undefined;
    }
  ),
}
Example #2
Source File: ObjIdConfigCodeActionProvider.ts    From al-objid with MIT License 6 votes vote down vote up
public async provideCodeActions(
        document: TextDocument,
        range: Range,
        context: CodeActionContext
    ): Promise<CodeAction[] | undefined> {
        const ninjaIssues = context.diagnostics.filter(diagnostic => diagnostic.source === "Ninja");
        if (ninjaIssues.length === 0) {
            return;
        }

        const app = WorkspaceManager.instance.getALAppFromUri(document.uri);
        if (!app) {
            return;
        }

        const actions: CodeAction[] = [];
        for (let issue of ninjaIssues) {
            const action = QuickFix[issue.code as string]({ actions, app, document, range });
            if (action instanceof Promise) {
                await action;
            }
        }
        return actions;
    }
Example #3
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
public provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(CodeAction | Command)[]> {
        this.QuickFixActions = [];

        return new Promise(resolve => {
            resolve(this.ProvideCodeActionsAsync(document, range, context, token));
         });
    }
Example #4
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
private async ProvideCodeActionsAsync(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): Promise<(CodeAction | Command)[] | null | undefined> {
        let alObject: ALObject | null = await ALSyntaxUtil.GetALObject(document);
        if (alObject === null) {
            return;
        }

        context.diagnostics.filter(diagnostics => diagnostics.source === ALXmlDocDiagnosticPrefix).forEach(diagnostic => {
            if (diagnostic === undefined) {
                return;
            }

            let diagCodes: Array<string> = [];
            if (diagnostic.code!.toString().indexOf(',') !== -1) { // multiple diagnostic codes
                diagnostic.code!.toString().split(', ').forEach(diagnosticCode => {
                    diagCodes.push(diagnosticCode);
                });
            } else { // just one diagnostic code
                diagCodes.push(diagnostic.code!.toString());
            }
            diagCodes.forEach(diagnosticCode => {
                let alProcedure: ALProcedure | undefined;
                if ((diagnosticCode !== ALXmlDocDiagnosticCode.ObjectDocumentationMissing) && (diagnosticCode !== ALXmlDocDiagnosticCode.ParameterUnnecessary)) {
                    alProcedure = alObject?.Procedures?.find(alProcedure => (alProcedure.LineNo === range.start.line));
                    if (alProcedure === undefined) {
                        console.error(`[ProvideCodeActionsAsync] - Unable to locate ALProcedure object for diagnostics entry. Please report this error at https://github.com/365businessdev/vscode-alxmldocumentation/issues`);
                        return;
                    }
                }

                switch (diagnosticCode) {
                    case ALXmlDocDiagnosticCode.DocumentationMissing:
                        this.AddDocumentationMissingCodeAction(alProcedure, diagnostic);
                        break;
                    case ALXmlDocDiagnosticCode.SummaryMissing:
                        this.AddSummaryDocumentationMissingCodeAction(alProcedure, diagnostic);
                        break;
                    case ALXmlDocDiagnosticCode.ParameterMissing:
                        this.AddParameterDocumentationMissingCodeAction(alProcedure, diagnostic);
                        break;
                    case ALXmlDocDiagnosticCode.ReturnTypeMissing:
                        this.AddReturnDocumentationMissingCodeAction(alProcedure, diagnostic);
                        break;
                    case ALXmlDocDiagnosticCode.ParameterUnnecessary:
                        this.AddUnnecessaryParameterDocumentationMissingCodeAction(alProcedure, diagnostic);
                        break;
                    case ALXmlDocDiagnosticCode.ObjectDocumentationMissing:
                        this.AddObjectDocumentationMissingCodeAction(alObject, diagnostic);
                        break;
                }
            });

        });
        
        return this.QuickFixActions;
    }
Example #5
Source File: codeActionProvider.ts    From dendron with GNU Affero General Public License v3.0 4 votes vote down vote up
refactorProvider: CodeActionProvider = {
  provideCodeActions: sentryReportingCallback(
    async (
      _document: TextDocument,
      _range: Range | Selection,
      _context: CodeActionContext,
      _token: CancellationToken
    ) => {
      // No-op if we're not in a Dendron Workspace
      const ext = ExtensionProvider.getExtension();
      if (!(await ext.isActiveAndIsDendronNote(_document.uri.fsPath))) {
        return;
      }

      const { editor, selection, text } = VSCodeUtils.getSelection();
      if (!editor || !selection) return;

      const header = getHeaderAt({
        document: editor.document,
        position: selection.start,
      });

      // action declaration
      const renameHeaderAction = {
        title: "Rename Header",
        isPreferred: true,
        kind: CodeActionKind.RefactorInline,
        command: {
          command: new RenameHeaderCommand().key,
          title: "Rename Header",
          arguments: [{ source: ContextualUIEvents.ContextualUICodeAction }],
        },
      };
      const brokenWikilinkAction = {
        title: "Add missing note for wikilink declaration",
        isPreferred: true,
        kind: CodeActionKind.RefactorExtract,
        command: {
          command: new GotoNoteCommand(ExtensionProvider.getExtension()).key,
          title: "Add missing note for wikilink declaration",
          arguments: [{ source: ContextualUIEvents.ContextualUICodeAction }],
        },
      };
      const createNewNoteAction = {
        title: "Extract text to new note",
        isPreferred: true,
        kind: CodeActionKind.RefactorExtract,
        command: {
          command: new NoteLookupCommand().key,
          title: "Extract text to new note",
          arguments: [
            {
              selectionType: LookupSelectionTypeEnum.selectionExtract,
              source: ContextualUIEvents.ContextualUICodeAction,
            },
          ],
        },
      };

      const copyHeaderRefAction = {
        title: "Copy Header Reference",
        isPreferred: true,
        kind: CodeActionKind.RefactorInline,
        command: {
          command: new CopyNoteRefCommand().key,
          title: "Copy Header Reference",
          arguments: [{ source: ContextualUIEvents.ContextualUICodeAction }],
        },
      };

      const WrapAsMarkdownLink = {
        title: "Wrap as Markdown Link",
        isPreferred: true,
        kind: CodeActionKind.RefactorInline,
        command: {
          command: new PasteLinkCommand().key,
          title: "Wrap as Markdown Link",
          arguments: [
            {
              source: ContextualUIEvents.ContextualUICodeAction,
              link: text,
              selection,
            },
          ],
        },
      };

      if (_range.isEmpty) {
        const { engine } = ext.getDWorkspace();
        const note = new WSUtilsV2(ext).getActiveNote();
        //return a code action for create note if user clicked next to a broken wikilink
        if (
          note &&
          (await isBrokenWikilink({ editor, engine, note, selection }))
        ) {
          return [brokenWikilinkAction];
        }

        //return a code action for rename header and copy header ref if user clicks next to a header
        if (!_.isUndefined(header)) {
          return [renameHeaderAction, copyHeaderRefAction];
        }
        // return if none
        return;
      } else {
        //regex for url
        if (!_.isUndefined(text) && isUrl(text)) {
          return [WrapAsMarkdownLink];
        }
        return !_.isUndefined(header)
          ? [createNewNoteAction, renameHeaderAction, copyHeaderRefAction]
          : [createNewNoteAction];
      }
    }
  ),
}
Example #6
Source File: actionProvider.ts    From typescript-explicit-types with GNU General Public License v3.0 4 votes vote down vote up
public async provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext): Promise<CodeAction[]> {
    const config = workspace.getConfiguration(configurationId);
    const isPreferrable = config.get<boolean>(ConfigurationKey.preferable);

    const allDefinitions: Location[] = [];
    for (let lineNumber = range.start.line; lineNumber <= range.end.line; lineNumber++) {
      const line = document.lineAt(lineNumber);
      const startCharNumber = lineNumber === range.start.line ? range.start.character : 0;
      const endCharNumber = lineNumber === range.end.line ? range.end.character : line.range.end.character;
      for (let charNumber = startCharNumber; charNumber <= endCharNumber; charNumber++) {
        const foundDefinitions = await executeDefinitionProvider(document.uri, new Position(lineNumber, charNumber));
        if (foundDefinitions?.length) allDefinitions.push(foundDefinitions[0]);
      }
    }

    if (!allDefinitions.length) return [];

    const definitions = uniqWith(allDefinitions, (a, b) => a.originSelectionRange.isEqual(b.originSelectionRange));
    const symbols = await executeSymbolProvider(document.uri);

    const generateTypeInfos: GenerateTypeInfo[] = [];
    for (const definition of definitions) {
      const hoverRes = await executeHoverProvider(document.uri, definition.originSelectionRange.start);
      if (!hoverRes) continue;

      // check if definition has a typescript annotation
      const tsHoverContent = hoverRes
        .reduce<string[]>((acc, val) => acc.concat(val.contents.map((x) => x.value)), [])
        .find((x) => x.includes('typescript'));
      if (!tsHoverContent) continue;

      const word = document.getText(definition.originSelectionRange);
      const lineText = document.getText(document.lineAt(definition.originSelectionRange.start.line).range);

      // => is recognized as a definition, but it's type is usually defined before, unlike all other types
      if (word === '=>') {
        // check that there are arrow functions without type on this line
        const regexp = /\)\s*=>/gm;
        const matches = findMatches(regexp, lineText);
        const indexes = matches.map((x) => x.index);
        if (!matches.length) continue;

        const passedIndex = indexes.find((i) => i > definition.originSelectionRange.start.character);

        // look for a potential index of a match
        // there might be several arrow functions on the same line & this definition might actually be one with a type
        const potentialIndexIndex = passedIndex ? indexes.indexOf(passedIndex) - 1 : indexes.length - 1;
        if (potentialIndexIndex < 0) continue;

        // check that our match contains the definition
        const potentialIndex = indexes[potentialIndexIndex];
        const definitionMatch = matches![potentialIndexIndex];
        if (
          potentialIndex >= definition.originSelectionRange.start.character ||
          potentialIndex + definitionMatch[0].length <= definition.originSelectionRange.start.character
        )
          continue;

        generateTypeInfos.push({
          isFunction: true,
          typescriptHoverResult: tsHoverContent,
          typePosition: new Position(definition.originSelectionRange.start.line, potentialIndex + 1),
        });
        continue;
      }

      const symbol = symbols?.find((x) => x.selectionRange.contains(definition.originSelectionRange));
      const trailingSlice = document.getText(new Range(definition.originSelectionRange.end, definition.targetRange.end));
      const isFollowedByBracket = !!trailingSlice.match(/^(\s|\\[rn])*\(/);
      if (symbol?.kind === SymbolKind.Function || word === 'function' || isFollowedByBracket) {
        // find out suitable type position by looking for a closing bracket of the function
        const offset = document.offsetAt(definition.originSelectionRange.end);
        const firstBracket = trailingSlice.indexOf('(');
        const closingBracketIndex = findClosingBracketMatchIndex(trailingSlice, firstBracket);

        const isFunctionTyped = trailingSlice.slice(closingBracketIndex + 1).match(/^\s*:/);
        if (isFunctionTyped) continue;

        const definitionSlice = document.getText(definition.targetRange);
        const firstSymbol = definitionSlice.match(/^\w+/);

        generateTypeInfos.push({
          typescriptHoverResult: tsHoverContent,
          typePosition: document.positionAt(offset + closingBracketIndex + 1),
          isFunction: !firstSymbol || !functionHandlerExceptions.includes(firstSymbol[0]),
        });
      } else {
        // check if type annotation is already present
        const typePosition = new Position(definition.originSelectionRange.end.line, definition.originSelectionRange.end.character);
        const slice = lineText.slice(typePosition.character);
        const match = slice.match(/^\s*:/g);
        if (match?.length) continue;

        generateTypeInfos.push({
          typescriptHoverResult: tsHoverContent,
          typePosition,
        });
      }
    }

    if (!generateTypeInfos.length) return [];

    const action = new CodeAction('Generate explicit type', CodeActionKind.QuickFix);
    const args: Parameters<typeof commandHandler> = [generateTypeInfos];
    action.command = { command: 'extension.generateExplicitType', title: 'Generate explicit type', arguments: args };
    action.isPreferred = isPreferrable;

    return [action];
  }