vscode#Diagnostic TypeScript Examples

The following examples show how to use vscode#Diagnostic. 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: cfgLinter.ts    From sourcepawn-vscode with MIT License 6 votes vote down vote up
/**
 * Lint a Valve Key Value TextDocument object and add its diagnostics to the collection.
 * @param  {TextDocument} document    The document to lint.
 * @returns void
 */
export function refreshCfgDiagnostics(document: TextDocument): void {
  // Check if the setting to activate the linter is set to true.
  const workspaceFolder = Workspace.getWorkspaceFolder(document.uri);
  const enableLinter = Workspace.getConfiguration(
    "sourcepawn",
    workspaceFolder
  ).get<boolean>("enableLinter");

  // Stop early if linter is disabled.
  if (!(enableLinter && cfgLangID.includes(document.languageId))) {
    cfgDiagnostics.set(document.uri, []);
    return;
  }
  cfgDiagnostics.delete(document.uri);
  try {
    const par = parse(document.getText(), undefined);
  } catch (e) {
    if (e instanceof SyntaxError) {
      const range = new Range(
        e.location.start.line - 1,
        e.location.start.column - 1,
        e.location.end.line - 1,
        e.location.end.column - 1
      );

      const msg = e.name + " " + e.message;
      const diag = new Diagnostic(range, msg);
      cfgDiagnostics.set(document.uri, [diag]);
    }
  }
}
Example #2
Source File: holes.ts    From vscode-lean4 with Apache License 2.0 6 votes vote down vote up
private async refresh() {
        const ress = await Promise.all(window.visibleTextEditors
            .filter((editor) => languages.match(this.leanDocs, editor.document))
            .map((editor) => this.server.allHoleCommands(editor.document.fileName)));

        this.holes = [];
        for (const res of ress) {
            [].push.apply(this.holes, res.holes);
        }

        const holesPerFile = new Map<string, HoleCommands[]>();
        for (const hole of this.holes) {
            if (!holesPerFile.get(hole.file)) { holesPerFile.set(hole.file, []); }
            holesPerFile.get(hole.file).push(hole);
        }

        this.collection.clear();
        for (const file of holesPerFile.keys()) {
            this.collection.set(Uri.file(file),
                holesPerFile.get(file).map((hole) =>
                    new Diagnostic(mkRange(hole),
                        'Hole: ' + hole.results.map((a) => a.name).join('/'),
                        DiagnosticSeverity.Hint)));
        }
    }
Example #3
Source File: sqlFluffLinter.ts    From vscode-sqlfluff with MIT License 6 votes vote down vote up
public process(lines: string[]): Diagnostic[] {
		let diagnostics: Diagnostic[] = [];
		lines.forEach((line) => {
			let filePaths: Array<FilePath> = JSON.parse(line);

			filePaths.forEach((filePath: FilePath) => {
				filePath.violations.forEach((violation: Violation) => {
					diagnostics.push({
						range: new Range(violation.line_no-1, violation.line_pos, violation.line_no-1, violation.line_pos),
						severity: DiagnosticSeverity.Error,
						message: violation.description,
						code: violation.code,
						source: 'sqlfluff'
					});
				});
			});

		});
		return diagnostics;
	}
Example #4
Source File: relatedErrorView.ts    From ide-vscode with MIT License 6 votes vote down vote up
public updateRelatedErrors(uri: Uri, diagnostics: Diagnostic[]): void {
    const documentPath = getVsDocumentPath({ uri: uri.toString() });
    const relatedErrorView: IRelatedErrorView = {
      ranges: diagnostics.flatMap(diagnostic =>
        diagnostic.relatedInformation == null || diagnostic.relatedInformation.length === 0
        || !diagnostic.message.startsWith('A postcondition might not hold')
          ? []
          : [ diagnostic.relatedInformation[0].location.range ])
    };
    this.relatedViewByDocument.set(documentPath, relatedErrorView);
    this.refreshRelatedErrors(window.activeTextEditor);
  }
Example #5
Source File: relatedErrorView.ts    From ide-vscode with MIT License 6 votes vote down vote up
public static createAndRegister(context: ExtensionContext, languageClient: DafnyLanguageClient): RelatedErrorView {
    RelatedErrorView.instance = new RelatedErrorView();
    context.subscriptions.push(
      workspace.onDidCloseTextDocument(document => RelatedErrorView.instance.clearRelatedErrors(document.uri.toString())),
      window.onDidChangeActiveTextEditor(editor => RelatedErrorView.instance.refreshRelatedErrors(editor)),
      RelatedErrorView.instance
    );
    languageClient.onPublishDiagnostics((uri: Uri, diagnostics: Diagnostic[]) => {
      RelatedErrorView.instance.updateRelatedErrors(uri, diagnostics);
    });
    return RelatedErrorView.instance;
  }
Example #6
Source File: stripeLinter.ts    From vscode-stripe with MIT License 6 votes vote down vote up
lookForHardCodedAPIKeys = async (document: TextDocument): Promise<void> => {
    performance.mark('ignore-start');
    const isIgnored = await this.git.isIgnored(document.uri);
    performance.mark('ignore-end');
    performance.measure('ignore', 'ignore-start', 'ignore-end');

    if (isIgnored || document.fileName.endsWith('.env')) {
      diagnosticCollection.delete(document.uri);
      return;
    }

    const text = document.getText();
    const lines = text.split('\n');

    const message = (await this.git.isGitRepo(document.uri))
      ? diagnosticMessageGit
      : diagnosticMessageNoGit;

    const fileDiagnostics: Diagnostic[] = lines.flatMap(this.prepareLineDiagnostics(message));

    // tell VS Code to show warnings and errors in syntax
    diagnosticCollection.set(document.uri, fileDiagnostics);
  };
Example #7
Source File: dafnyLanguageClient.ts    From ide-vscode with MIT License 6 votes vote down vote up
public static async create(context: ExtensionContext, statusOutput: OutputChannel): Promise<DafnyLanguageClient> {
    const { path: dotnetExecutable } = await getDotnetExecutablePath();
    const launchArguments = [ getLanguageServerRuntimePath(context), ...getLanguageServerLaunchArgs() ];
    statusOutput.appendLine(`Language server arguments: ${DafnyLanguageClient.argumentsToCommandLine(launchArguments)}`);
    const serverOptions: ServerOptions = {
      run: { command: dotnetExecutable, args: launchArguments },
      debug: { command: dotnetExecutable, args: launchArguments }
    };
    const diagnosticsListeners: ((uri: Uri, diagnostics: Diagnostic[]) => void)[] = [];
    const clientOptions: LanguageClientOptions = {
      documentSelector: [ DafnyDocumentFilter ],
      diagnosticCollectionName: LanguageServerId,
      middleware: {
        handleDiagnostics: (uri: Uri, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature) => {
          for(const handler of diagnosticsListeners) {
            handler(uri, diagnostics);
          }
          next(uri, diagnostics);
        }
      }
    };
    return new DafnyLanguageClient(LanguageServerId, LanguageServerName, serverOptions, clientOptions, diagnosticsListeners);
  }
Example #8
Source File: stripeLinter.ts    From vscode-stripe with MIT License 6 votes vote down vote up
// prepareAPIKeyDiagnostics regex matches all instances of a Stripe API Key in a supplied line of text
  // will return a list of Diagnostics pointing at instances of the Stripe API Keys it found
  prepareLineDiagnostics =
    (message: string) =>
    (line: string, index: number): Diagnostic[] => {
      const diagnostics: Diagnostic[] = [];

      let match;
      while ((match = stripeKeysRegex.exec(line)) !== null) {
        const severity = /sk_live/.test(match[0])
          ? DiagnosticSeverity.Error
          : DiagnosticSeverity.Warning;

        // specify line and character range to draw the squiggly line under the API Key in the document
        const range = new Range(index, match.index, index, match.index + match[0].length);
        // create new diagnostic and add to the list of total diagnostics for this line of code
        const diagnostic = new Diagnostic(range, message, severity);

        this.telemetry.sendEvent('diagnostics.show', severity);
        diagnostics.push(diagnostic);
      }

      return diagnostics;
    };
Example #9
Source File: lexMode.ts    From yash with MIT License 6 votes vote down vote up
export function getLEXMode(lexLanguageService: LEXLanguageService): LanguageMode {
    const cache = CreateDocumentCache<LexDocument>(10, 60, document => lexLanguageService.parseLexDocument(document));
    return {
        getId() {
            return 'lex';
        },
        doValidation(document: TextDocument): Diagnostic[] {
            const lex = cache.get(document);
            return lexLanguageService.doValidation(document, lex);
        },
        doComplete(document: TextDocument, position: Position): CompletionList | CompletionItem[] {
            const lex = cache.get(document);
            return lexLanguageService.doComplete(document, position, lex);
        },
        doHover(document: TextDocument, position: Position): Hover | null {
            const lex = cache.get(document);
            return lexLanguageService.doHover(document, position, lex);
        },
        findDefinition(document: TextDocument, position: Position): Definition | null {
            const lex = cache.get(document);
            return lexLanguageService.findDefinition(document, position, lex);
        },
        findReferences(document: TextDocument, position: Position): Location[] {
            const lex = cache.get(document);
            return lexLanguageService.findReferences(document, position, lex);
        },
        doRename(document: TextDocument, position: Position, newName: string): WorkspaceEdit | null {
            const lex = cache.get(document);
            return lexLanguageService.doRename(document, position, newName, lex);
        },
        onDocumentRemoved(document: TextDocument) {
            cache.onDocumentRemoved(document);
        },
        dispose() {
            cache.dispose();
        }
    };
}
Example #10
Source File: yaccValidation.ts    From yash with MIT License 6 votes vote down vote up
export function doYACCValidation(document: TextDocument, yaccDocument: YACCDocument): Diagnostic[] {
    const diags: Diagnostic[] = [];
    yaccDocument.problems.forEach(problem => {
        const range = new Range(document.positionAt(problem.offset), document.positionAt(problem.end));
        let severity: DiagnosticSeverity = DiagnosticSeverity.Information;
        switch (problem.type) {
            case ProblemType.Error:
                severity = DiagnosticSeverity.Error;
                break;
            case ProblemType.Information:
                severity = DiagnosticSeverity.Information;
                break;
            case ProblemType.Warning:
                severity = DiagnosticSeverity.Warning;
                break;
        }
        const diag = new Diagnostic(range, problem.message, severity);
        if (problem.related) {
            diag.relatedInformation = [new DiagnosticRelatedInformation(
                new Location(document.uri, new Range(document.positionAt(problem.related.offset), document.positionAt(problem.related.end))),
                problem.related.message
            )];
        }
        diags.push(diag);
    });
    return diags;
}
Example #11
Source File: lexValidation.ts    From yash with MIT License 6 votes vote down vote up
export function doLEXValidation(document: TextDocument, lexDocument: LexDocument): Diagnostic[] {
    const diags: Diagnostic[] = [];
    lexDocument.problems.forEach(problem => {
        const range = new Range(document.positionAt(problem.offset), document.positionAt(problem.end));
        let severity: DiagnosticSeverity = DiagnosticSeverity.Information;
        switch (problem.type) {
            case ProblemType.Error:
                severity = DiagnosticSeverity.Error;
                break;
            case ProblemType.Information:
                severity = DiagnosticSeverity.Information;
                break;
            case ProblemType.Warning:
                severity = DiagnosticSeverity.Warning;
                break;
        }
        const diag = new Diagnostic(range, problem.message, severity);
        if (problem.related) {
            diag.relatedInformation = [new DiagnosticRelatedInformation(
                new Location(document.uri, new Range(document.positionAt(problem.related.offset), document.positionAt(problem.related.end))),
                problem.related.message
            )];
        }
        diags.push(diag);
    });
    return diags;
}
Example #12
Source File: parseSPCompErrors.ts    From sourcepawn-vscode with MIT License 6 votes vote down vote up
export function parseSPCompErrors(
  stdout: string,
  compilerDiagnostics: DiagnosticCollection,
  filePath?: string
): void {
  const DocumentDiagnostics: Map<string, Diagnostic[]> = new Map();
  const re = /([:\/\\A-Za-z\-_0-9. ]*)\((\d+)+\) : ((error|fatal error|warning) ([0-9]*)):\s+(.*)/gm;
  let matches: RegExpExecArray | null;
  let diagnostics: Diagnostic[];
  do {
    matches = re.exec(stdout.toString() || "");
    if (matches) {
      let range = new Range(
        new Position(Number(matches[2]) - 1, 0),
        new Position(Number(matches[2]) - 1, 256)
      );
      let severity =
        matches[4] === "warning"
          ? DiagnosticSeverity.Warning
          : DiagnosticSeverity.Error;
      let uri = URI.file(
        filePath === undefined ? matches[1] : filePath
      ).toString();
      diagnostics = DocumentDiagnostics.get(uri) || [];

      let message: string = generateDetailedError(matches[5], matches[6]);
      let diagnostic: Diagnostic = new Diagnostic(range, message, severity);
      diagnostics.push(diagnostic);
      DocumentDiagnostics.set(uri, diagnostics);
    }
  } while (matches);
  compilerDiagnostics.clear();
  for (let [uri, diagnostics] of DocumentDiagnostics) {
    compilerDiagnostics.set(URI.parse(uri), diagnostics);
  }
}
Example #13
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix unnecessary Parameter XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddUnnecessaryParameterDocumentationMissingCodeAction(alProcedure: ALProcedure | undefined, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Remove unnecessary parameter XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixUnnecessaryParameterDocumentation`,
            title: 'Remove unnecessary parameter XML documentation',
            tooltip: `Automatically fix unnecessary parameter XML documentation for procedure ${alProcedure?.Name}.`,
            arguments: [alProcedure, diagnostic.range]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #14
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix Return Value XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddReturnDocumentationMissingCodeAction(alProcedure: ALProcedure | undefined, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Add return value XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixReturnDocumentation`,
            title: 'Add return value XML documentation',
            tooltip: `Automatically fix missing return value XML documentation for procedure ${alProcedure?.Name}.`,
            arguments: [alProcedure]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #15
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix Parameter XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddParameterDocumentationMissingCodeAction(alProcedure: ALProcedure | undefined, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Add parameter XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixParameterDocumentation`,
            title: 'Add parameter XML documentation',
            tooltip: `Automatically fix missing parameter XML documentation for procedure ${alProcedure?.Name}.`,
            arguments: [alProcedure]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #16
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix Summary XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddSummaryDocumentationMissingCodeAction(alProcedure: ALProcedure | undefined, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Add summary XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixSummaryDocumentation`,
            title: 'Add procedure summary XML documentation',
            tooltip: `Automatically fix missing summary XML documentation for procedure ${alProcedure?.Name}.`,
            arguments: [alProcedure]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #17
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix Procedure XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddDocumentationMissingCodeAction(alProcedure: ALProcedure | undefined, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Add XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixDocumentation`,
            title: 'Add procedure XML documentation',
            tooltip: `Automatically fix missing XML documentation for procedure ${alProcedure?.Name}.`,
            arguments: [alProcedure]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #18
Source File: ALDocumentationQuickFix.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Add Code Action to fix Object XML Documentation missing.
     * @param alProcedure AL Procedure.
     * @param diagnostic Diagnostic entry.
     */
    private AddObjectDocumentationMissingCodeAction(alObject: ALObject | null, diagnostic: Diagnostic) {
        let action: CodeAction = new CodeAction('Add XML documentation', CodeActionKind.QuickFix);
        action.command = {
            command: `${ALXmlDocConfigurationPrefix}.fixObjectDocumentation`,
            title: 'Add object XML documentation',
            tooltip: `Automatically fix missing XML documentation for object ${alObject?.Name}.`,
            arguments: [alObject]
        };
        action.diagnostics = [diagnostic];
        action.isPreferred = true;
        this.QuickFixActions.push(action);
    }
Example #19
Source File: Diagnostics.ts    From al-objid with MIT License 6 votes vote down vote up
public createDiagnostics(uri: Uri, category: string): CreateDiagnostic {
        let document = this._documents.get(uri);
        if (!document) {
            document = {};
            this._documents.set(uri, document);
        }
        document[category] = [];

        const newDiagnostics = (document[category] = [] as Diagnostic[]);
        const scheduleUpdate = () => {
            const scheduler = this._schedulers.get(uri);
            if (scheduler) {
                clearTimeout(scheduler);
            }
            this._schedulers.set(
                uri,
                setTimeout(() => {
                    const set: Diagnostic[] = [];
                    for (let key of Object.keys(document!)) {
                        set.push(...document![key]);
                    }
                    this._diagnostics.set(uri, set);
                }, 1000)
            );
        };

        // Makes sure that diagnostics are reported at least once
        scheduleUpdate();

        return (range, message, severity, code) => {
            const diagnostic = new Diagnostic(range, message, severity);
            diagnostic.source = "Ninja";
            diagnostic.code = code;
            newDiagnostics.push(diagnostic);
            scheduleUpdate();
            return diagnostic;
        };
    }
Example #20
Source File: ALCheckDocumentation.ts    From vscode-alxmldocumentation with MIT License 6 votes vote down vote up
/**
     * Analyse documentation of the given object.
     * @param alObject 
     */
    private AnalyzeObjectDocumentation(alObject: ALObject) {
        if (alObject === null) {
            return;
        }

        if (!Configuration.IsDocumentationMandatoryForAccessLevel(alObject.Access)) {
            return;
        }
        
        if (alObject.ALDocumentation.Exists === ALDocumentationExists.No) {            
            let diagnostic = new Diagnostic(alObject.Range!, 
                `XML documentation is expected for Object ${alObject.Name}.`, 
                Configuration.GetObjectDocumentationCheckInformationLevel(alObject.Uri));
            diagnostic.source = ALXmlDocDiagnosticPrefix;
            diagnostic.code = ALXmlDocDiagnosticCode.ObjectDocumentationMissing;

            this.diags.push(diagnostic);
        }
    }
Example #21
Source File: leanclient.ts    From vscode-lean4 with Apache License 2.0 5 votes vote down vote up
async getDiagnosticParams(uri: Uri, diagnostics: readonly Diagnostic[]) : Promise<PublishDiagnosticsParams> {
        const params: PublishDiagnosticsParams = {
            uri: c2pConverter.asUri(uri),
            diagnostics: await c2pConverter.asDiagnostics(diagnostics as Diagnostic[])
        };
        return params;
    }
Example #22
Source File: yaccMode.ts    From yash with MIT License 5 votes vote down vote up
export function getYACCMode(yaccLanguageService: YACCLanguageService): LanguageMode {
    const cache = CreateDocumentCache<YACCDocument>(10, 60, document => yaccLanguageService.parseYACCDocument(document));
    return {
        getId() {
            return 'yacc';
        },
        doValidation(document: TextDocument, force?:boolean): Diagnostic[] {
            if (force) {
                return yaccLanguageService.doValidation(document, yaccLanguageService.parseYACCDocument(document));
            }
            const yacc = cache.get(document);
            return yaccLanguageService.doValidation(document, yacc);
        },
        doComplete(document: TextDocument, position: Position): CompletionList | CompletionItem[] {
            const yacc = cache.get(document);
            return yaccLanguageService.doComplete(document, position, yacc);
        },
        doHover(document: TextDocument, position: Position): Hover | null {
            const yacc = cache.get(document);
            return yaccLanguageService.doHover(document, position, yacc);
        },
        findTypeDefinition(document: TextDocument, position: Position): Definition | null {
            const yacc = cache.get(document);
            return yaccLanguageService.findTypeDefinition(document, position, yacc);
        },
        findDefinition(document: TextDocument, position: Position): Definition | null {
            const yacc = cache.get(document);
            return yaccLanguageService.findDefinition(document, position, yacc);
        },
        findReferences(document: TextDocument, position: Position): Location[] {
            const yacc = cache.get(document);
            return yaccLanguageService.findReferences(document, position, yacc);
        },
        doRename(document: TextDocument, position: Position, newName: string): WorkspaceEdit | null {
            const yacc = cache.get(document);
            return yaccLanguageService.doRename(document, position, newName, yacc);
        },
        getSemanticTokens(document: TextDocument): SemanticTokenData[] {
            const yacc = cache.get(document);
            return yaccLanguageService.getSemanticTokens(document, yacc);
        },
        getSemanticTokenLegend() {
            return { types: tokenTypes, modifiers: tokenModifiers };
        },
        onDocumentRemoved(document: TextDocument) {
            cache.onDocumentRemoved(document);
        },
        dispose() {
            cache.dispose();
        }
    };
}
Example #23
Source File: leanclient.ts    From vscode-lean4 with Apache License 2.0 5 votes vote down vote up
export function getFullRange(diag: Diagnostic): Range {
    return (diag as any)?.fullRange || diag.range;
}
Example #24
Source File: Diagnostics.ts    From al-objid with MIT License 5 votes vote down vote up
private _documents = new WeakMap<Uri, PropertyBag<Diagnostic[]>>();
Example #25
Source File: frontmatter.ts    From dendron with GNU Affero General Public License v3.0 5 votes vote down vote up
delayedFrontmatterWarning = _.debounce(
  (uri: Uri, diagnostics: Diagnostic[]) => {
    FRONTMATTER_WARNING.set(uri, diagnostics);
  },
  500
)
Example #26
Source File: dafnyLanguageClient.ts    From ide-vscode with MIT License 5 votes vote down vote up
public onPublishDiagnostics(callback: (uri: Uri, diagnostics: Diagnostic[]) => void): void {
    this.diagnosticsListeners.push(callback);
  }
Example #27
Source File: ALCheckDocumentation.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
/**
     * Analyze procedure for unnecessary XML documentations.
     * @param codeLines AL Source Code.
     * @param currentLineNo Actual line no. in AL Source Code.
     * @param documentation Captured XML documentation.
     * @param alObject ALObject
     * @param alProcedure ALProcedure
     */
    private GetUnnecessaryProcedureDocumentationDiagnostics(codeLines: string[], currentLineNo: number, documentation: string, alObject: ALObject, alProcedure: ALProcedure) {
        // convert to JSON to make it more accessible 
        let jsonDocumentation = ALDocCommentUtil.GetJsonFromALDocumentation(documentation);
        if (!jsonDocumentation.param) {
            return;
        }

        let unnecessaryParameters: Array<string> = [];

        if (jsonDocumentation.param.length) { // multiple parameters
            for (let i = 0; i < jsonDocumentation.param.length; i++) {
                this.GetUnnecessaryParameterDocumentationDiagnostics(unnecessaryParameters, jsonDocumentation.param[i], alProcedure);
            }
        } else { // one parameter
            this.GetUnnecessaryParameterDocumentationDiagnostics(unnecessaryParameters, jsonDocumentation.param, alProcedure);
        }

        if (unnecessaryParameters.length !== 0) {
            let message = '';
            unnecessaryParameters.forEach(parameter => {
                message = StringUtil.AppendString(message, `'${parameter}'`, ', ');

                let paramRange: Range = alProcedure.Range!;
                for (let i = currentLineNo; i >= 0; i--) {
                    if (codeLines[i].indexOf(`/// <param name="${parameter}">`) !== -1) {
                        paramRange = ALSyntaxUtil.GetRange(codeLines.join('\r\n'), i);
                        break;
                    }
                }

                message = `Parameter '${parameter}' is described in XML documentation for procedure ${alProcedure.Name}, but do not exist in procedure signature.`;
                let diagnostic = new Diagnostic(paramRange,
                    message, 
                    Configuration.GetProcedureDocumentationCheckInformationLevel(alObject.Uri));
                diagnostic.source = ALXmlDocDiagnosticPrefix;
                diagnostic.code = this.GetDiagnosticCode(ALXmlDocDiagnosticCode.ParameterUnnecessary);
    
                this.diags.push(diagnostic);
            });
        }
    }
Example #28
Source File: ALCheckDocumentation.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
/**
     * Gathered diagnostics.
     */
    private diags: Diagnostic[] = [];
Example #29
Source File: leanclient.ts    From vscode-lean4 with Apache License 2.0 4 votes vote down vote up
async restart(): Promise<void> {
        const startTime = Date.now()

        console.log('Restarting Lean Language Server')
        if (this.isStarted()) {
            await this.stop()
        }

        this.restartingEmitter.fire(undefined)
        this.toolchainPath = this.storageManager.getLeanPath();
        if (!this.toolchainPath) this.toolchainPath = toolchainPath();
        const version = this.storageManager.getLeanVersion();
        const env = addServerEnvPaths(process.env);
        if (serverLoggingEnabled()) {
            env.LEAN_SERVER_LOG_DIR = serverLoggingPath()
        }

        let executable = (this.toolchainPath) ? join(this.toolchainPath, 'bin', 'lake') : 'lake';

        // check if the lake process will start (skip it on scheme: 'untitled' files)
        let useLake = lakeEnabled() && this.folderUri && this.folderUri.scheme === 'file';
        if (useLake) {
            let knownDate = false;
            const lakefile = Uri.joinPath(this.folderUri, 'lakefile.lean')
            if (!await fileExists(new URL(lakefile.toString()))) {
                useLake = false;
            }
            else {
                // see if we can avoid the more expensive checkLakeVersion call.
                const date = await this.checkToolchainVersion(this.folderUri);
                if (date){
                    // Feb 16 2022 is when the 3.1.0.pre was released.
                    useLake = date >= new Date(2022, 1, 16);
                    knownDate = true;
                }
                if (useLake && !knownDate){
                    useLake = await this.checkLakeVersion(executable, version);
                }
            }
        }

        if (!useLake) {
            executable = (this.toolchainPath) ? join(this.toolchainPath, 'bin', 'lean') : 'lean';
        }

        let options = version ? ['+' + version] :[]
        if (useLake) {
            options = options.concat(['serve', '--'])
        } else{
            options = options.concat(['--server'])
        }

        // Add folder name to command-line so that it shows up in `ps aux`.
        if (this.folderUri) {
            options.push('' + this.folderUri.fsPath)
        } else {
            options.push('untitled')
        }

        const serverOptions: ServerOptions = {
            command: executable,
            args: options.concat(serverArgs()),
            options: {
                cwd: this.folderUri?.fsPath,
                env
            }
        }

        const documentSelector: DocumentFilter = {
            language: 'lean4'
        }

        if (this.folderUri){
            documentSelector.scheme = this.folderUri.scheme
            if (this.folderUri.scheme !== 'untitled') {
                documentSelector.pattern = `${this.folderUri.fsPath}/**/*`
            }
        }

        const clientOptions: LanguageClientOptions = {
            outputChannel: this.outputChannel,
            documentSelector: [documentSelector],
            workspaceFolder: this.workspaceFolder,
            initializationOptions: {
                editDelay: getElaborationDelay(), hasWidgets: true,
            },
            connectionOptions: {
                maxRestartCount: 0,
                cancellationStrategy: undefined as any,
            },
            middleware: {
                handleDiagnostics: (uri, diagnostics, next) => {
                    next(uri, diagnostics);
                    if (!this.client) return;
                    const uri_ = c2pConverter.asUri(uri);
                    const diagnostics_ = [];
                    for (const d of diagnostics) {
                        const d_: ls.Diagnostic = {
                            ...c2pConverter.asDiagnostic(d),
                        };
                        diagnostics_.push(d_);
                    }
                    this.diagnosticsEmitter.fire({uri: uri_, diagnostics: diagnostics_});
                },

                didOpen: async () => {
                    // Note: as per the LSP spec: An open notification must not be sent more than once
                    // without a corresponding close notification send before. This means open and close
                    // notification must be balanced and the max open count for a particular textDocument
                    // is one.  So this even does nothing the notification is handled by the
                    // openLean4Document method below after the 'lean4' languageId is established and
                    // it has weeded out documents opened to invisible editors (like 'git:' schemes and
                    // invisible editors created for Ctrl+Hover events.  A side effect of unbalanced
                    // open/close notification is leaking 'lean --worker' processes.
                    // See https://github.com/microsoft/vscode/issues/78453).
                    return;
                },

                didChange: async (data, next) => {
                    await next(data);
                    if (!this.running || !this.client) return; // there was a problem starting lean server.
                    const params = c2pConverter.asChangeTextDocumentParams(data);
                    this.didChangeEmitter.fire(params);
                },

                didClose: async (doc, next) => {
                    if (!this.isOpen.delete(doc.uri.toString())) {
                        return;
                    }
                    await next(doc);
                    if (!this.running || !this.client) return; // there was a problem starting lean server.
                    const params = c2pConverter.asCloseTextDocumentParams(doc);
                    this.didCloseEmitter.fire(params);
                },

                provideDocumentHighlights: async (doc, pos, ctok, next) => {
                    const leanHighlights = await next(doc, pos, ctok);
                    if (leanHighlights?.length) return leanHighlights;

                    // vscode doesn't fall back to textual highlights,
                    // so we need to do that manually
                    await new Promise((res) => setTimeout(res, 250));
                    if (ctok.isCancellationRequested) return;

                    const wordRange = doc.getWordRangeAtPosition(pos);
                    if (!wordRange) return;
                    const word = doc.getText(wordRange);

                    const highlights: DocumentHighlight[] = [];
                    const text = doc.getText();
                    const nonWordPattern = '[`~@$%^&*()-=+\\[{\\]}⟨⟩⦃⦄⟦⟧⟮⟯‹›\\\\|;:\",./\\s]|^|$'
                    const regexp = new RegExp(`(?<=${nonWordPattern})${escapeRegExp(word)}(?=${nonWordPattern})`, 'g')
                    for (const match of text.matchAll(regexp)) {
                        const start = doc.positionAt(match.index ?? 0)
                        highlights.push({
                            range: new Range(start, start.translate(0, match[0].length)),
                            kind: DocumentHighlightKind.Text,
                        })
                    }

                    return highlights;
                }
            },
        }
        this.client = new LanguageClient(
            'lean4',
            'Lean 4',
            serverOptions,
            clientOptions
        )
        let insideRestart = true;
        patchConverters(this.client.protocol2CodeConverter, this.client.code2ProtocolConverter)
        try {
            this.client.onDidChangeState(async (s) => {
                // see https://github.com/microsoft/vscode-languageserver-node/issues/825
                if (s.newState === State.Starting) {
                    console.log('client starting');
                } else if (s.newState === State.Running) {
                    const end = Date.now()
                    console.log('client running, started in ', end - startTime, 'ms');
                    this.running = true; // may have been auto restarted after it failed.
                    if (!insideRestart) {
                        this.restartedEmitter.fire(undefined)
                    }
                } else if (s.newState === State.Stopped) {
                    this.stoppedEmitter.fire('Lean language server has stopped. ');
                    console.log('client has stopped or it failed to start');
                    this.running = false;
                    if (!this.noPrompt){
                        await this.showRestartMessage();
                    }
                }
            })
            this.client.start()
            await this.client.onReady();
            // tell the new client about the documents that are already open!
            for (const key of this.isOpen.keys()) {
                const doc = this.isOpen.get(key);
                if (doc) this.notifyDidOpen(doc);
            }
            // if we got this far then the client is happy so we are running!
            this.running = true;
        } catch (error) {
            this.outputChannel.appendLine('' + error);
            this.serverFailedEmitter.fire('' + error);
            insideRestart = false;
            return;
        }

        // HACK(WN): Register a default notification handler to fire on custom notifications.
        // A mechanism to do this is provided in vscode-jsonrpc. One can register a `StarNotificationHandler`
        // here: https://github.com/microsoft/vscode-languageserver-node/blob/b2fc85d28a1a44c22896559ee5f4d3ba37a02ef5/jsonrpc/src/common/connection.ts#L497
        // which fires on any LSP notifications not in the standard, for example the `$/lean/..` ones.
        // However this mechanism is not exposed in vscode-languageclient, so we hack around its implementation.
        const starHandler = (method: string, params_: any) => {
            if (method === '$/lean/fileProgress' && this.client) {
                const params = params_ as LeanFileProgressParams;
                const uri = p2cConverter.asUri(params.textDocument.uri)
                this.progressChangedEmitter.fire([uri.toString(), params.processing]);
                // save the latest progress on this Uri in case infoview needs it later.
                this.progress.set(uri, params.processing);
            }

            this.customNotificationEmitter.fire({method, params: params_});
        };
        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
        this.client.onNotification(starHandler as any, () => {});

        // Reveal the standard error output channel when the server prints something to stderr.
        // The vscode-languageclient library already takes care of writing it to the output channel.
        (this.client as any)._serverProcess.stderr.on('data', () => {
            this.client?.outputChannel.show(true);
        });

        this.restartedEmitter.fire(undefined)
        insideRestart = false;
    }