Skip to content
This repository has been archived by the owner on Nov 5, 2021. It is now read-only.

Add types for TypeScriptWorker and missing LanguageServiceDefaults methods #54

Merged
merged 6 commits into from Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions src/monaco.contribution.ts
Expand Up @@ -208,11 +208,11 @@ const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false });

function getTypeScriptWorker(): Promise<any> {
function getTypeScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> {
return getMode().then(mode => mode.getTypeScriptWorker());
}

function getJavaScriptWorker(): Promise<any> {
function getJavaScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> {
return getMode().then(mode => mode.getJavaScriptWorker());
}

Expand Down
216 changes: 207 additions & 9 deletions src/monaco.d.ts
Expand Up @@ -49,6 +49,7 @@ declare module monaco.languages.typescript {
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUmdGlobalAccess?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
Expand All @@ -60,6 +61,7 @@ declare module monaco.languages.typescript {
emitDeclarationOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
disableSourceOfProjectReferenceRedirect?: boolean;
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
Expand Down Expand Up @@ -111,8 +113,10 @@ declare module monaco.languages.typescript {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
Expand All @@ -122,6 +126,7 @@ declare module monaco.languages.typescript {
/** Paths used to compute primary types search locations */
typeRoots?: string[];
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | undefined;
}

Expand All @@ -132,7 +137,69 @@ declare module monaco.languages.typescript {
diagnosticCodesToIgnore?: number[];
}

interface IExtraLib {
content: string;
version: number;
}

interface IExtraLibs {
[path: string]: IExtraLib;
}

/**
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
* It is built from the bottom up, leaving the head to be the "main" diagnostic.
*/
interface DiagnosticMessageChain {
messageText: string;
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
next?: DiagnosticMessageChain[];
}
interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
interface DiagnosticRelatedInformation {
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
/** TypeScriptWorker removes this to avoid serializing circular JSON structures. */
file: undefined;
start: number | undefined;
length: number | undefined;
messageText: string | DiagnosticMessageChain;
}

interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}

export interface LanguageServiceDefaults {
/**
* Event fired when compiler options or diagnostics options are changed.
*/
readonly onDidChange: IEvent<void>;

/**
* Event fired when extra libraries registered with the language service change.
*/
readonly onDidExtraLibsChange: IEvent<void>;

/**
* Get the current extra libs registered with the language service.
*/
getExtraLibs(): IExtraLibs;

/**
* Add an additional source file to the language service. Use this
* for typescript (definition) files that won't be loaded as editor
Expand All @@ -153,22 +220,29 @@ declare module monaco.languages.typescript {
*/
setExtraLibs(libs: { content: string; filePath?: string }[]): void;

/**
* Get current TypeScript compiler options for the language service.
*/
getCompilerOptions(): CompilerOptions;

/**
* Set TypeScript compiler options.
*/
setCompilerOptions(options: CompilerOptions): void;

/**
* Get the current diagnostics options for the language service.
*/
getDiagnosticsOptions(): DiagnosticsOptions;

/**
* Configure whether syntactic and/or semantic validation should
* be performed
*/
setDiagnosticsOptions(options: DiagnosticsOptions): void;

/**
* Configure when the worker shuts down. By default that is 2mins.
*
* @param value The maximum idle time in milliseconds. Values less than one
* mean never shut down.
* No-op.
*/
setMaximumWorkerIdleTime(value: number): void;

Expand All @@ -177,13 +251,137 @@ declare module monaco.languages.typescript {
* to the worker on start or restart.
*/
setEagerModelSync(value: boolean): void;

/**
* Get the current setting for whether all existing models should be eagerly sync'd
* to the worker on start or restart.
*/
getEagerModelSync(): boolean;
}

export interface TypeScriptWorker {
/**
* Get diagnostic messages for any syntax issues in the given file.
*/
getSyntacticDiagnostics(fileName: string): Promise<Diagnostic[]>;

/**
* Get diagnostic messages for any semantic issues in the given file.
*/
getSemanticDiagnostics(fileName: string): Promise<Diagnostic[]>;

/**
* Get diagnostic messages for any suggestions related to the given file.
*/
getSuggestionDiagnostics(fileName: string): Promise<Diagnostic[]>;

/**
* Get diagnostic messages related to the current compiler options.
* @param fileName Not used
*/
getCompilerOptionsDiagnostics(fileName: string): Promise<Diagnostic[]>;

/**
* Get code completions for the given file and position.
* @returns `Promise<typescript.CompletionInfo | undefined>`
*/
getCompletionsAtPosition(fileName: string, position: number): Promise<any | undefined>;

/**
* Get code completion details for the given file, position, and entry.
* @returns `Promise<typescript.CompletionEntryDetails | undefined>`
*/
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<any | undefined>;

/**
* Get signature help items for the item at the given file and position.
* @returns `Promise<typescript.SignatureHelpItems | undefined>`
*/
getSignatureHelpItems(fileName: string, position: number): Promise<any | undefined>;

/**
* Get quick info for the item at the given position in the file.
* @returns `Promise<typescript.QuickInfo | undefined>`
*/
getQuickInfoAtPosition(fileName: string, position: number): Promise<any | undefined>;

/**
* Get other ranges which are related to the item at the given position in the file (often used for highlighting).
* @returns `Promise<ReadonlyArray<typescript.ReferenceEntry> | undefined>`
*/
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>;

/**
* Get the definition of the item at the given position in the file.
* @returns `Promise<ReadonlyArray<typescript.DefinitionInfo> | undefined>`
*/
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>;

/**
* Get references to the item at the given position in the file.
* @returns `Promise<typescript.ReferenceEntry[] | undefined>`
*/
getReferencesAtPosition(fileName: string, position: number): Promise<any[] | undefined>;

/**
* Get outline entries for the item at the given position in the file.
* @returns `Promise<typescript.NavigationBarItem[]>`
*/
getNavigationBarItems(fileName: string): Promise<any[]>;

/**
* Get changes which should be applied to format the given file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForDocument(fileName: string, options: any): Promise<any[]>;

/**
* Get changes which should be applied to format the given range in the file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForRange(fileName: string, start: number, end: number, options: any): Promise<any[]>;

/**
* Get formatting changes which should be applied after the given keystroke.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsAfterKeystroke(fileName: string, postion: number, ch: string, options: any): Promise<any[]>;

/**
* Get other occurrences which should be updated when renaming the item at the given file and position.
* @returns `Promise<readonly typescript.RenameLocation[] | undefined>`
*/
findRenameLocations(fileName: string, positon: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename: boolean): Promise<readonly any[] | undefined>;

/**
* Get edits which should be applied to rename the item at the given file and position (or a failure reason).
* @param options `typescript.RenameInfoOptions`
* @returns `Promise<typescript.RenameInfo>`
*/
getRenameInfo(fileName: string, positon: number, options: any): Promise<any>;

/**
* Get transpiled output for the given file.
* @returns `typescript.EmitOutput`
*/
getEmitOutput(fileName: string): Promise<any>;

/**
* Get possible code fixes at the given position in the file.
* @param formatOptions `typescript.FormatCodeOptions`
* @returns `Promise<ReadonlyArray<typescript.CodeFixAction>>`
*/
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: any): Promise<ReadonlyArray<any>>;
}

export var typescriptVersion: string;
export const typescriptVersion: string;

export var typescriptDefaults: LanguageServiceDefaults;
export var javascriptDefaults: LanguageServiceDefaults;
export const typescriptDefaults: LanguageServiceDefaults;
export const javascriptDefaults: LanguageServiceDefaults;

export var getTypeScriptWorker: () => Promise<any>;
export var getJavaScriptWorker: () => Promise<any>;
export const getTypeScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>;
export const getJavaScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>;
}
14 changes: 7 additions & 7 deletions src/tsMode.ts
Expand Up @@ -11,8 +11,8 @@ import * as languageFeatures from './languageFeatures';

import Uri = monaco.Uri;

let javaScriptWorker: (first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>;
let typeScriptWorker: (first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>;
let javaScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
let typeScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;

export function setupTypeScript(defaults: LanguageServiceDefaultsImpl): void {
typeScriptWorker = setupMode(
Expand All @@ -28,7 +28,7 @@ export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
);
}

export function getJavaScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> {
export function getJavaScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> {
return new Promise((resolve, reject) => {
if (!javaScriptWorker) {
return reject("JavaScript not registered!");
Expand All @@ -38,7 +38,7 @@ export function getJavaScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => P
});
}

export function getTypeScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> {
export function getTypeScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> {
return new Promise((resolve, reject) => {
if (!typeScriptWorker) {
return reject("TypeScript not registered!");
Expand All @@ -48,11 +48,11 @@ export function getTypeScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => P
});
}

function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker> {
function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (...uris: Uri[]) => Promise<TypeScriptWorker> {

const client = new WorkerManager(modeId, defaults);
const worker = (first: Uri, ...more: Uri[]): Promise<TypeScriptWorker> => {
return client.getLanguageServiceWorker(...[first].concat(more));
const worker = (...uris: Uri[]): Promise<TypeScriptWorker> => {
return client.getLanguageServiceWorker(...uris);
};

monaco.languages.registerCompletionItemProvider(modeId, new languageFeatures.SuggestAdapter(worker));
Expand Down
25 changes: 11 additions & 14 deletions src/tsWorker.ts
Expand Up @@ -20,7 +20,7 @@ const ES6_LIB = {
CONTENTS: lib_es6_dts
};

export class TypeScriptWorker implements ts.LanguageServiceHost {
export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.languages.typescript.TypeScriptWorker {

// --- model sync -----------------------

Expand Down Expand Up @@ -123,7 +123,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {

// --- language features

private static clearFiles(diagnostics: ts.Diagnostic[]) {
private static clearFiles(diagnostics: ts.Diagnostic[]): monaco.languages.typescript.Diagnostic[] {
// Clear the `file` field, which cannot be JSON'yfied because it
// contains cyclic data structures.
diagnostics.forEach(diag => {
Expand All @@ -133,30 +133,27 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
related.forEach(diag2 => diag2.file = undefined);
}
});
return <monaco.languages.typescript.Diagnostic[]>diagnostics;
}

getSyntacticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
getSyntacticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}

getSemanticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
getSemanticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}

getSuggestionDiagnostics(fileName: string): Promise<ts.DiagnosticWithLocation[]> {
getSuggestionDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSuggestionDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}

getCompilerOptionsDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
getCompilerOptionsDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}

getCompletionsAtPosition(fileName: string, position: number): Promise<ts.CompletionInfo | undefined> {
Expand Down