Give a higher priority to language configuration set via API call (#114684)

上级 ed8043ef
......@@ -57,33 +57,21 @@ export class RichEditSupport {
public readonly indentationRules: IndentationRule | undefined;
public readonly foldingRules: FoldingRules;
constructor(languageIdentifier: LanguageIdentifier, previous: RichEditSupport | undefined, rawConf: LanguageConfiguration) {
constructor(languageIdentifier: LanguageIdentifier, rawConf: LanguageConfiguration) {
this._languageIdentifier = languageIdentifier;
this._brackets = null;
this._electricCharacter = null;
let prev: LanguageConfiguration | null = null;
if (previous) {
prev = previous._conf;
}
this._conf = RichEditSupport._mergeConf(prev, rawConf);
this._conf = rawConf;
this._onEnterSupport = (this._conf.brackets || this._conf.indentationRules || this._conf.onEnterRules ? new OnEnterSupport(this._conf) : null);
this.comments = RichEditSupport._handleComments(this._conf);
this.characterPair = new CharacterPairSupport(this._conf);
this.wordDefinition = this._conf.wordPattern || DEFAULT_WORD_REGEXP;
this.indentationRules = this._conf.indentationRules;
if (this._conf.indentationRules) {
this.indentRulesSupport = new IndentRulesSupport(this._conf.indentationRules);
} else {
this.indentRulesSupport = null;
}
this.foldingRules = this._conf.folding || {};
}
......@@ -108,21 +96,6 @@ export class RichEditSupport {
return this._onEnterSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText);
}
private static _mergeConf(prev: LanguageConfiguration | null, current: LanguageConfiguration): LanguageConfiguration {
return {
comments: (prev ? current.comments || prev.comments : current.comments),
brackets: (prev ? current.brackets || prev.brackets : current.brackets),
wordPattern: (prev ? current.wordPattern || prev.wordPattern : current.wordPattern),
indentationRules: (prev ? current.indentationRules || prev.indentationRules : current.indentationRules),
onEnterRules: (prev ? current.onEnterRules || prev.onEnterRules : current.onEnterRules),
autoClosingPairs: (prev ? current.autoClosingPairs || prev.autoClosingPairs : current.autoClosingPairs),
surroundingPairs: (prev ? current.surroundingPairs || prev.surroundingPairs : current.surroundingPairs),
autoCloseBefore: (prev ? current.autoCloseBefore || prev.autoCloseBefore : current.autoCloseBefore),
folding: (prev ? current.folding || prev.folding : current.folding),
__electricCharacterSupport: (prev ? current.__electricCharacterSupport || prev.__electricCharacterSupport : current.__electricCharacterSupport),
};
}
private static _handleComments(conf: LanguageConfiguration): ICommentsConfiguration | null {
let commentRule = conf.comments;
if (!commentRule) {
......@@ -151,38 +124,120 @@ export class LanguageConfigurationChangeEvent {
) { }
}
export class LanguageConfigurationRegistryImpl {
class LanguageConfigurationEntry {
constructor(
public readonly configuration: LanguageConfiguration,
public readonly priority: number,
public readonly order: number
) { }
private readonly _entries = new Map<LanguageId, RichEditSupport | undefined>();
public static cmp(a: LanguageConfigurationEntry, b: LanguageConfigurationEntry) {
if (a.priority === b.priority) {
// higher order last
return a.order - b.order;
}
// higher priority last
return a.priority - b.priority;
}
}
private readonly _onDidChange = new Emitter<LanguageConfigurationChangeEvent>();
public readonly onDidChange: Event<LanguageConfigurationChangeEvent> = this._onDidChange.event;
class LanguageConfigurationEntries {
public register(languageIdentifier: LanguageIdentifier, configuration: LanguageConfiguration): IDisposable {
let previous = this._getRichEditSupport(languageIdentifier.id);
let current = new RichEditSupport(languageIdentifier, previous, configuration);
this._entries.set(languageIdentifier.id, current);
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
private readonly _entries: LanguageConfigurationEntry[];
private _order: number;
private _resolved: RichEditSupport | null = null;
constructor(
public readonly languageIdentifier: LanguageIdentifier
) {
this._entries = [];
this._order = 0;
this._resolved = null;
}
public register(configuration: LanguageConfiguration, priority: number): IDisposable {
const entry = new LanguageConfigurationEntry(configuration, priority, ++this._order);
this._entries.push(entry);
this._resolved = null;
return toDisposable(() => {
if (this._entries.get(languageIdentifier.id) === current) {
this._entries.set(languageIdentifier.id, previous);
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
for (let i = 0; i < this._entries.length; i++) {
if (this._entries[i] === entry) {
this._entries.splice(i, 1);
this._resolved = null;
break;
}
}
});
}
private _getRichEditSupport(languageId: LanguageId): RichEditSupport | undefined {
return this._entries.get(languageId);
public getRichEditSupport(): RichEditSupport | null {
if (!this._resolved) {
const config = this._resolve();
if (config) {
this._resolved = new RichEditSupport(this.languageIdentifier, config);
}
}
return this._resolved;
}
public getIndentationRules(languageId: LanguageId) {
const value = this._entries.get(languageId);
if (!value) {
private _resolve(): LanguageConfiguration | null {
if (this._entries.length === 0) {
return null;
}
this._entries.sort(LanguageConfigurationEntry.cmp);
const result: LanguageConfiguration = {};
for (const entry of this._entries) {
const conf = entry.configuration;
result.comments = conf.comments || result.comments;
result.brackets = conf.brackets || result.brackets;
result.wordPattern = conf.wordPattern || result.wordPattern;
result.indentationRules = conf.indentationRules || result.indentationRules;
result.onEnterRules = conf.onEnterRules || result.onEnterRules;
result.autoClosingPairs = conf.autoClosingPairs || result.autoClosingPairs;
result.surroundingPairs = conf.surroundingPairs || result.surroundingPairs;
result.autoCloseBefore = conf.autoCloseBefore || result.autoCloseBefore;
result.folding = conf.folding || result.folding;
result.__electricCharacterSupport = conf.__electricCharacterSupport || result.__electricCharacterSupport;
}
return result;
}
}
return value.indentationRules || null;
export class LanguageConfigurationRegistryImpl {
private readonly _entries2 = new Map<LanguageId, LanguageConfigurationEntries>();
private readonly _onDidChange = new Emitter<LanguageConfigurationChangeEvent>();
public readonly onDidChange: Event<LanguageConfigurationChangeEvent> = this._onDidChange.event;
/**
* @param priority Use a higher number for higher priority
*/
public register(languageIdentifier: LanguageIdentifier, configuration: LanguageConfiguration, priority: number = 0): IDisposable {
let entries = this._entries2.get(languageIdentifier.id);
if (!entries) {
entries = new LanguageConfigurationEntries(languageIdentifier);
this._entries2.set(languageIdentifier.id, entries);
}
const disposable = entries.register(configuration, priority);
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
return toDisposable(() => {
disposable.dispose();
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
});
}
private _getRichEditSupport(languageId: LanguageId): RichEditSupport | null {
const entries = this._entries2.get(languageId);
return entries ? entries.getRichEditSupport() : null;
}
public getIndentationRules(languageId: LanguageId): IndentationRule | null {
const value = this._getRichEditSupport(languageId);
return value ? value.indentationRules || null : null;
}
// begin electricCharacter
......@@ -273,11 +328,12 @@ export class LanguageConfigurationRegistryImpl {
public getWordDefinitions(): [LanguageId, RegExp][] {
let result: [LanguageId, RegExp][] = [];
this._entries.forEach((value, language) => {
for (const [language, entries] of this._entries2) {
const value = entries.getRichEditSupport();
if (value) {
result.push([language, value.wordDefinition]);
}
});
}
return result;
}
......
......@@ -84,4 +84,4 @@ LanguageConfigurationRegistry.register(PLAINTEXT_LANGUAGE_IDENTIFIER, {
folding: {
offSide: true
}
});
}, 0);
......@@ -68,7 +68,7 @@ export function setLanguageConfiguration(languageId: string, configuration: Lang
if (!languageIdentifier) {
throw new Error(`Cannot set configuration for unknown language ${languageId}`);
}
return LanguageConfigurationRegistry.register(languageIdentifier, configuration);
return LanguageConfigurationRegistry.register(languageIdentifier, configuration, 100);
}
/**
......
......@@ -4,8 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { StandardTokenType } from 'vs/editor/common/modes';
import { LanguageIdentifier, StandardTokenType } from 'vs/editor/common/modes';
import { StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
suite('StandardAutoClosingPairConditional', () => {
......@@ -88,4 +89,13 @@ suite('StandardAutoClosingPairConditional', () => {
assert.strictEqual(v.isOK(StandardTokenType.String), false);
assert.strictEqual(v.isOK(StandardTokenType.RegEx), false);
});
test('language configurations priorities', () => {
const id = new LanguageIdentifier('testLang1', 15);
const d1 = LanguageConfigurationRegistry.register(id, { comments: { lineComment: '1' } }, 100);
const d2 = LanguageConfigurationRegistry.register(id, { comments: { lineComment: '2' } }, 10);
assert.strictEqual(LanguageConfigurationRegistry.getComments(id.id)?.lineCommentToken, '1');
d1.dispose();
d2.dispose();
});
});
......@@ -727,7 +727,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
const languageIdentifier = this._modeService.getLanguageIdentifier(languageId);
if (languageIdentifier) {
this._registrations.set(handle, LanguageConfigurationRegistry.register(languageIdentifier, configuration));
this._registrations.set(handle, LanguageConfigurationRegistry.register(languageIdentifier, configuration, 100));
}
}
......
......@@ -398,7 +398,7 @@ export class LanguageConfigurationFileHandler {
richEditConfig.onEnterRules = onEnterRules;
}
LanguageConfigurationRegistry.register(languageIdentifier, richEditConfig);
LanguageConfigurationRegistry.register(languageIdentifier, richEditConfig, 50);
}
private _parseRegex(languageIdentifier: LanguageIdentifier, confPath: string, value: string | IRegExp) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册