import LSTypes from 'vscode-languageserver-types'; import { CancellationToken, IDisposable, IRelativePattern, MarkerSeverity, Uri } from '@opensumi/ide-core-common'; import { editor } from '@opensumi/ide-monaco'; import type { IRelatedInformation } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers'; export const ILanguageService = Symbol('ILanguageService'); export interface ILanguageService { languages: Language[]; workspaceSymbolProviders: WorkspaceSymbolProvider[]; getLanguage(languageId: string): Language | undefined; registerWorkspaceSymbolProvider(provider: WorkspaceSymbolProvider): IDisposable; } export interface DiagnosticCollection extends IDisposable { set(uri: string, diagnostics: Diagnostic[]): void; } /** * Represents a related message and source code location for a diagnostic. This should be * used to point to code locations that cause or related to a diagnostics, e.g when duplicating * a symbol in a scope. */ export interface DiagnosticRelatedInformation { /** * The location of this related diagnostic information. */ location: LSTypes.Location; /** * The message of this related diagnostic information. */ message: string; } /** * The DiagnosticRelatedInformation namespace provides helper functions to work with * [DiagnosticRelatedInformation](#DiagnosticRelatedInformation) literals. */ export declare namespace DiagnosticRelatedInformation { /** * Creates a new DiagnosticRelatedInformation literal. */ function create(location: Location, message: string): DiagnosticRelatedInformation; /** * Checks whether the given literal conforms to the [DiagnosticRelatedInformation](#DiagnosticRelatedInformation) interface. */ function is(value: any): value is DiagnosticRelatedInformation; } export enum DiagnosticSeverity { Error = 1, Warning = 2, Information = 3, Hint = 4, } /** * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects * are only valid in the scope of a resource. */ export interface Diagnostic { /** * The range at which the message applies */ range: LSTypes.Range; /** * The diagnostic's severity. Can be omitted. If omitted it is up to the * client to interpret diagnostics as error, warning, info or hint. */ severity: DiagnosticSeverity; /** * A code or identifier for this diagnostic. * Should be used for later processing, e.g. when providing {@link CodeActionContext code actions}. */ code?: | string | number | { /** * A code or identifier for this diagnostic. * Should be used for later processing, e.g. when providing {@link CodeActionContext code actions}. */ value: string | number; /** * A target URI to open with more information about the diagnostic error. */ target: Uri; }; /** * A human-readable string describing the source of this * diagnostic, e.g. 'typescript' or 'super lint'. */ source?: string; /** * The diagnostic's message. */ message: string; /** * An array of related diagnostic information, e.g. when symbol-names within * a scope collide all definitions can be marked via this property. */ relatedInformation?: DiagnosticRelatedInformation[]; tags?: DiagnosticTag[]; } export enum DiagnosticTag { Unnecessary = 1, Deprecated = 2, } export function asSeverity(severity?: number): MarkerSeverity { if (severity === 1) { return MarkerSeverity.Error; } if (severity === 2) { return MarkerSeverity.Warning; } if (severity === 3) { return MarkerSeverity.Info; } return MarkerSeverity.Hint; } export function asRelatedInformations( relatedInformation?: DiagnosticRelatedInformation[], ): IRelatedInformation[] | undefined { if (!relatedInformation) { return undefined; } return relatedInformation.map((item) => asRelatedInformation(item)); } export function asRelatedInformation(relatedInformation: DiagnosticRelatedInformation): IRelatedInformation { return { resource: Uri.parse(relatedInformation.location.uri), startLineNumber: relatedInformation.location.range.start.line + 1, startColumn: relatedInformation.location.range.start.character + 1, endLineNumber: relatedInformation.location.range.end.line + 1, endColumn: relatedInformation.location.range.end.character + 1, message: relatedInformation.message, }; } export function asMonacoDiagnostics(diagnostics: Diagnostic[] | undefined): editor.IMarkerData[] | undefined { if (!diagnostics) { return undefined; } return diagnostics.map((diagnostic) => asMonacoDiagnostic(diagnostic)); } export function asMonacoDiagnostic(diagnostic: Diagnostic): editor.IMarkerData { return { code: typeof diagnostic.code === 'number' ? diagnostic.code.toString() : typeof diagnostic.code === 'object' ? { value: diagnostic.code.value.toString(), target: diagnostic.code.target, } : diagnostic.code, severity: asSeverity(diagnostic.severity), message: diagnostic.message, source: diagnostic.source, // language server range is 0-based, marker is 1-based startLineNumber: diagnostic.range.start.line + 1, startColumn: diagnostic.range.start.character + 1, endLineNumber: diagnostic.range.end.line + 1, endColumn: diagnostic.range.end.character + 1, relatedInformation: asRelatedInformations(diagnostic.relatedInformation), tags: diagnostic.tags as number[], }; } export interface WorkspaceSymbolParams { query: string; } export interface WorkspaceSymbolProvider { provideWorkspaceSymbols( params: WorkspaceSymbolParams, token: CancellationToken, ): Thenable; resolveWorkspaceSymbol( symbol: LSTypes.SymbolInformation, token: CancellationToken, ): Thenable; } export interface Language { readonly id: string; readonly name: string; readonly extensions: Set; readonly filenames: Set; } export interface LanguageFilter { language?: string; scheme?: string; pattern?: string | IRelativePattern; hasAccessToAllModels?: boolean; notebookType?: string; } export type LanguageSelector = string | LanguageFilter | (string | LanguageFilter)[];