mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge pull request #58703 from Microsoft/aeschli/tokenizersupport-initialization
ITokenizationRegistry to support TokenizationSupport promises
This commit is contained in:
@@ -1186,12 +1186,23 @@ export interface ITokenizationRegistry {
|
||||
*/
|
||||
register(language: string, support: ITokenizationSupport): IDisposable;
|
||||
|
||||
/**
|
||||
* Register a promise for a tokenization support.
|
||||
*/
|
||||
registerPromise(language: string, promise: Thenable<ITokenizationSupport>): Thenable<IDisposable>;
|
||||
|
||||
/**
|
||||
* Get the tokenization support for a language.
|
||||
* Returns null if not found.
|
||||
*/
|
||||
get(language: string): ITokenizationSupport;
|
||||
|
||||
/**
|
||||
* Get the promise of a tokenization support for a language.
|
||||
* `null` is returned if no support is available and no promise for the support has been registered yet.
|
||||
*/
|
||||
getPromise(language: string): Thenable<ITokenizationSupport>;
|
||||
|
||||
/**
|
||||
* Set the new color map that all tokens will use in their ColorId binary encoded bits for foreground and background.
|
||||
*/
|
||||
|
||||
@@ -5,13 +5,19 @@
|
||||
'use strict';
|
||||
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IState, ITokenizationSupport, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes';
|
||||
import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode';
|
||||
import { ITokenizationSupport, IState, LanguageId } from 'vs/editor/common/modes';
|
||||
import { LineTokens, IViewLineTokens } from 'vs/editor/common/core/lineTokens';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode';
|
||||
|
||||
export function tokenizeToString(text: string, languageId: string): string {
|
||||
return _tokenizeToString(text, _getSafeTokenizationSupport(languageId));
|
||||
const fallback = {
|
||||
getInitialState: () => NULL_STATE,
|
||||
tokenize: undefined,
|
||||
tokenize2: (buffer: string, state: IState, deltaOffset: number) => nullTokenize2(LanguageId.Null, buffer, state, deltaOffset)
|
||||
};
|
||||
|
||||
export function tokenizeToString(text: string, tokenizationSupport: ITokenizationSupport = fallback): string {
|
||||
return _tokenizeToString(text, tokenizationSupport);
|
||||
}
|
||||
|
||||
export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens, colorMap: string[], startOffset: number, endOffset: number, tabSize: number): string {
|
||||
@@ -83,18 +89,6 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
|
||||
return result;
|
||||
}
|
||||
|
||||
function _getSafeTokenizationSupport(languageId: string): ITokenizationSupport {
|
||||
let tokenizationSupport = TokenizationRegistry.get(languageId);
|
||||
if (tokenizationSupport) {
|
||||
return tokenizationSupport;
|
||||
}
|
||||
return {
|
||||
getInitialState: () => NULL_STATE,
|
||||
tokenize: undefined,
|
||||
tokenize2: (buffer: string, state: IState, deltaOffset: number) => nullTokenize2(LanguageId.Null, buffer, state, deltaOffset)
|
||||
};
|
||||
}
|
||||
|
||||
function _tokenizeToString(text: string, tokenizationSupport: ITokenizationSupport): string {
|
||||
let result = `<div class="monaco-tokenized-source">`;
|
||||
let lines = text.split(/\r\n|\r|\n/);
|
||||
|
||||
@@ -8,10 +8,12 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
|
||||
private _map: { [language: string]: ITokenizationSupport };
|
||||
private _promises: { [language: string]: Thenable<IDisposable> };
|
||||
|
||||
private readonly _onDidChange: Emitter<ITokenizationSupportChangedEvent> = new Emitter<ITokenizationSupportChangedEvent>();
|
||||
public readonly onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event;
|
||||
@@ -20,6 +22,7 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
|
||||
constructor() {
|
||||
this._map = Object.create(null);
|
||||
this._promises = Object.create(null);
|
||||
this._colorMap = null;
|
||||
}
|
||||
|
||||
@@ -30,7 +33,7 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public register(language: string, support: ITokenizationSupport): IDisposable {
|
||||
public register(language: string, support: ITokenizationSupport) {
|
||||
this._map[language] = support;
|
||||
this.fire([language]);
|
||||
return toDisposable(() => {
|
||||
@@ -42,6 +45,26 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public registerPromise(language: string, supportPromise: Thenable<ITokenizationSupport>): Thenable<IDisposable> {
|
||||
const promise = this._promises[language] = supportPromise.then(support => {
|
||||
delete this._promises[language];
|
||||
return this.register(language, support);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
public getPromise(language: string): Thenable<ITokenizationSupport> {
|
||||
const support = this.get(language);
|
||||
if (support) {
|
||||
return TPromise.as(support);
|
||||
}
|
||||
const promise = this._promises[language];
|
||||
if (promise) {
|
||||
return promise.then(_ => this.get(language));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public get(language: string): ITokenizationSupport {
|
||||
return (this._map[language] || null);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { TokenizationRegistry } from 'vs/editor/common/modes';
|
||||
|
||||
export interface IMarkdownRenderResult extends IDisposable {
|
||||
element: HTMLElement;
|
||||
@@ -45,7 +46,11 @@ export class MarkdownRenderer {
|
||||
: this._editor.getModel().getLanguageIdentifier().language;
|
||||
|
||||
return this._modeService.getOrCreateMode(modeId).then(_ => {
|
||||
return tokenizeToString(value, modeId);
|
||||
const promise = TokenizationRegistry.getPromise(modeId);
|
||||
if (promise) {
|
||||
return promise.then(support => tokenizeToString(value, support));
|
||||
}
|
||||
return tokenizeToString(value, null);
|
||||
}).then(code => {
|
||||
return `<span style="font-family: ${this._editor.getConfiguration().fontInfo.fontFamily}">${code}</span>`;
|
||||
});
|
||||
|
||||
@@ -19,8 +19,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
|
||||
|
||||
test('TextToHtmlTokenizer 1', () => {
|
||||
let mode = new Mode();
|
||||
let support = TokenizationRegistry.get(mode.getId());
|
||||
|
||||
let actual = tokenizeToString('.abc..def...gh', mode.getId());
|
||||
let actual = tokenizeToString('.abc..def...gh', support);
|
||||
let expected = [
|
||||
{ className: 'mtk7', text: '.' },
|
||||
{ className: 'mtk9', text: 'abc' },
|
||||
@@ -38,8 +39,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
|
||||
|
||||
test('TextToHtmlTokenizer 2', () => {
|
||||
let mode = new Mode();
|
||||
let support = TokenizationRegistry.get(mode.getId());
|
||||
|
||||
let actual = tokenizeToString('.abc..def...gh\n.abc..def...gh', mode.getId());
|
||||
let actual = tokenizeToString('.abc..def...gh\n.abc..def...gh', support);
|
||||
let expected1 = [
|
||||
{ className: 'mtk7', text: '.' },
|
||||
{ className: 'mtk9', text: 'abc' },
|
||||
|
||||
@@ -11,7 +11,7 @@ import { OS } from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { asText } from 'vs/base/node/request';
|
||||
import { IMode, TokenizationRegistry } from 'vs/editor/common/modes';
|
||||
import { TokenizationRegistry, ITokenizationSupport } from 'vs/editor/common/modes';
|
||||
import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization';
|
||||
import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
@@ -192,21 +192,18 @@ export class ReleaseNotesManager {
|
||||
}
|
||||
|
||||
private async getRenderer(text: string) {
|
||||
const result: TPromise<IMode>[] = [];
|
||||
let result: TPromise<ITokenizationSupport>[] = [];
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.code = (code, lang) => {
|
||||
const modeId = this._modeService.getModeIdForLanguageName(lang);
|
||||
result.push(this._modeService.getOrCreateMode(modeId));
|
||||
result.push(this._modeService.getOrCreateMode(modeId).then(_ => TokenizationRegistry.getPromise(modeId)));
|
||||
return '';
|
||||
};
|
||||
|
||||
marked(text, { renderer });
|
||||
await TPromise.join(result);
|
||||
|
||||
renderer.code = (code, lang) => {
|
||||
const modeId = this._modeService.getModeIdForLanguageName(lang);
|
||||
return `<code>${tokenizeToString(code, modeId)}</code>`;
|
||||
};
|
||||
renderer.code = (code, lang) => `<code>${tokenizeToString(code, TokenizationRegistry.get(lang))}</code>`;
|
||||
return renderer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,9 +397,13 @@ export class TextMateService implements ITextMateService {
|
||||
}
|
||||
|
||||
private registerDefinition(modeId: string): void {
|
||||
this._createGrammar(modeId).then((r) => {
|
||||
TokenizationRegistry.register(modeId, new TMTokenization(this._scopeRegistry, r.languageId, r.grammar, r.initialState, r.containsEmbeddedLanguages, this._notificationService));
|
||||
}, onUnexpectedError);
|
||||
const promise = this._createGrammar(modeId).then((r) => {
|
||||
return new TMTokenization(this._scopeRegistry, r.languageId, r.grammar, r.initialState, r.containsEmbeddedLanguages, this._notificationService);
|
||||
}, e => {
|
||||
onUnexpectedError(e);
|
||||
return null;
|
||||
});
|
||||
TokenizationRegistry.registerPromise(modeId, promise);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user