Improve unusable slowness of tree sitter syntax highlighting (#229951)

* Improve unusable slowness of tree sitter syntax highlighting
Part of #229935

* Improve improvement as discussed with Martin

* Fix score

* Fix test error
This commit is contained in:
Alex Ross 2024-09-30 15:18:32 +02:00 коммит произвёл GitHub
Родитель a0991154fa
Коммит ef44e67783
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 55 добавлений и 86 удалений

Просмотреть файл

@ -1989,7 +1989,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -2507,7 +2507,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -2801,16 +2801,16 @@
}, },
{ {
"c": "t", "c": "t",
"t": "variable variable.other.constant", "t": "variable",
"r": { "r": {
"dark_plus": "variable.other.constant: #4FC1FF", "dark_plus": "variable: #9CDCFE",
"light_plus": "variable.other.constant: #0070C1", "light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4", "dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000", "light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE", "hc_black": "variable: #9CDCFE",
"dark_modern": "variable.other.constant: #4FC1FF", "dark_modern": "variable: #9CDCFE",
"hc_light": "variable.other.constant: #02715D", "hc_light": "variable: #001080",
"light_modern": "variable.other.constant: #0070C1" "light_modern": "variable: #001080"
} }
}, },
{ {

Просмотреть файл

@ -155,16 +155,16 @@
}, },
{ {
"c": "timeRange", "c": "timeRange",
"t": "variable variable.other.constant", "t": "variable",
"r": { "r": {
"dark_plus": "variable.other.constant: #4FC1FF", "dark_plus": "variable: #9CDCFE",
"light_plus": "variable.other.constant: #0070C1", "light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4", "dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000", "light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE", "hc_black": "variable: #9CDCFE",
"dark_modern": "variable.other.constant: #4FC1FF", "dark_modern": "variable: #9CDCFE",
"hc_light": "variable.other.constant: #02715D", "hc_light": "variable: #001080",
"light_modern": "variable.other.constant: #0070C1" "light_modern": "variable: #001080"
} }
}, },
{ {

Просмотреть файл

@ -85,16 +85,16 @@
}, },
{ {
"c": "foo", "c": "foo",
"t": "variable entity.name.function variable.other.constant", "t": "variable entity.name.function",
"r": { "r": {
"dark_plus": "variable.other.constant: #4FC1FF", "dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "variable.other.constant: #0070C1", "light_plus": "entity.name.function: #795E26",
"dark_vs": "default: #D4D4D4", "dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000", "light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE", "hc_black": "entity.name.function: #DCDCAA",
"dark_modern": "variable.other.constant: #4FC1FF", "dark_modern": "entity.name.function: #DCDCAA",
"hc_light": "variable.other.constant: #02715D", "hc_light": "entity.name.function: #5E2CBC",
"light_modern": "variable.other.constant: #0070C1" "light_modern": "entity.name.function: #795E26"
} }
}, },
{ {
@ -169,7 +169,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",

Просмотреть файл

@ -85,7 +85,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",

Просмотреть файл

@ -323,7 +323,7 @@
}, },
{ {
"c": "constructor", "c": "constructor",
"t": "variable meta.definition.method entity.name.function storage.type", "t": "variable meta.definition.method storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -1457,7 +1457,7 @@
}, },
{ {
"c": "constructor", "c": "constructor",
"t": "variable meta.definition.method entity.name.function storage.type", "t": "variable meta.definition.method storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -2717,7 +2717,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -3319,7 +3319,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",
@ -3879,7 +3879,7 @@
}, },
{ {
"c": "=>", "c": "=>",
"t": "keyword.operator storage.type", "t": "storage.type",
"r": { "r": {
"dark_plus": "storage.type: #569CD6", "dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF", "light_plus": "storage.type: #0000FF",

Просмотреть файл

@ -61,9 +61,10 @@
(function_declaration (function_declaration
name: (identifier) @entity.name.function) name: (identifier) @entity.name.function)
(method_definition (method_definition
name: (property_identifier) @meta.definition.method @entity.name.function) name: (property_identifier) @meta.definition.method @entity.name.function
(#not-eq? @entity.name.function "constructor"))
(method_definition (method_definition
name: (property_identifier) @storage.type name: (property_identifier) @meta.definition.method @storage.type
(#eq? @storage.type "constructor")) (#eq? @storage.type "constructor"))
(method_signature (method_signature
name: (property_identifier) @meta.definition.method @entity.name.function) name: (property_identifier) @meta.definition.method @entity.name.function)
@ -109,10 +110,6 @@
(predefined_type (["string" "boolean" "number" "any"])) @support.type.primitive (predefined_type (["string" "boolean" "number" "any"])) @support.type.primitive
(type_identifier) @entity.name.type (type_identifier) @entity.name.type
(("const")
(variable_declarator
name: (identifier) @variable.other.constant))
([ ([
(identifier) (identifier)
(shorthand_property_identifier) (shorthand_property_identifier)
@ -192,7 +189,6 @@
"<<=" "<<="
"==" "=="
"!=" "!="
"=>"
">>" ">>"
">>=" ">>="
">>>" ">>>"

Просмотреть файл

@ -26,7 +26,6 @@ import { ThemeConfiguration } from './themeConfiguration.js';
import { ColorScheme } from '../../../../platform/theme/common/theme.js'; import { ColorScheme } from '../../../../platform/theme/common/theme.js';
import { ColorId, FontStyle, MetadataConsts } from '../../../../editor/common/encodedTokenAttributes.js'; import { ColorId, FontStyle, MetadataConsts } from '../../../../editor/common/encodedTokenAttributes.js';
import { toStandardTokenType } from '../../../../editor/common/languages/supports/tokenization.js'; import { toStandardTokenType } from '../../../../editor/common/languages/supports/tokenization.js';
import { findMatchingThemeRule } from '../../textMate/common/TMHelper.js';
const colorRegistry = Registry.as<IColorRegistry>(ColorRegistryExtensions.ColorContribution); const colorRegistry = Registry.as<IColorRegistry>(ColorRegistryExtensions.ColorContribution);
@ -817,34 +816,25 @@ const defaultThemeColors: { [baseTheme: string]: ITextMateThemingRule[] } = {
const noMatch = (_scope: ProbeScope) => -1; const noMatch = (_scope: ProbeScope) => -1;
function nameMatcher(identifers: string[], scope: ProbeScope): number { function nameMatcher(identifiers: string[], scopes: ProbeScope): number {
function findInIdents(s: string, lastIndent: number): number { if (scopes.length < identifiers.length) {
for (let i = lastIndent - 1; i >= 0; i--) {
if (scopesAreMatching(s, identifers[i])) {
return i;
}
}
return -1; return -1;
} }
if (scope.length < identifers.length) {
return -1; let lastIndex = 0;
} let score: number | undefined = undefined;
let lastScopeIndex = scope.length - 1; const every = identifiers.every((identifier, identifierIndex) => {
let lastIdentifierIndex = findInIdents(scope[lastScopeIndex--], identifers.length); for (let i = lastIndex; i < scopes.length; i++) {
if (lastIdentifierIndex >= 0) { if (scopesAreMatching(scopes[i], identifier)) {
const score = (lastIdentifierIndex + 1) * 0x10000 + identifers[lastIdentifierIndex].length; score = (identifierIndex + 1) * 0x10000 + identifier.length;
while (lastScopeIndex >= 0) { lastIndex = i + 1;
lastIdentifierIndex = findInIdents(scope[lastScopeIndex--], lastIdentifierIndex); return true;
if (lastIdentifierIndex === -1) {
return -1;
} }
} }
return score; return false;
} });
return -1; return every && score !== undefined ? score : -1;
} }
function scopesAreMatching(thisScopeName: string, scopeName: string): boolean { function scopesAreMatching(thisScopeName: string, scopeName: string): boolean {
if (!thisScopeName) { if (!thisScopeName) {
return false; return false;
@ -906,18 +896,15 @@ export function findMetadata(colorThemeData: ColorThemeData, captureNames: strin
metadata |= (languageId << MetadataConsts.LANGUAGEID_OFFSET); metadata |= (languageId << MetadataConsts.LANGUAGEID_OFFSET);
const themeRule = findMatchingThemeRule(colorThemeData, captureNames); const definitions: TextMateThemingRuleDefinitions = {};
let tokenStyle: TokenStyle | undefined; const tokenStyle = colorThemeData.resolveScopes([captureNames], definitions);
if (!themeRule) {
tokenStyle = colorThemeData.resolveScopes(captureNames.map(name => [name]).reverse());
}
if (captureNames.length > 0) { if (captureNames.length > 0) {
const standardToken = toStandardTokenType(captureNames[captureNames.length - 1]); const standardToken = toStandardTokenType(captureNames[captureNames.length - 1]);
metadata |= (standardToken << MetadataConsts.TOKEN_TYPE_OFFSET); metadata |= (standardToken << MetadataConsts.TOKEN_TYPE_OFFSET);
} }
switch (themeRule?.settings.fontStyle) { switch (definitions.foreground?.settings.fontStyle) {
case 'italic': case 'italic':
metadata |= FontStyle.Italic | MetadataConsts.ITALIC_MASK; metadata |= FontStyle.Italic | MetadataConsts.ITALIC_MASK;
break; break;
@ -930,26 +917,9 @@ export function findMetadata(colorThemeData: ColorThemeData, captureNames: strin
case 'strikethrough': case 'strikethrough':
metadata |= FontStyle.Strikethrough | MetadataConsts.STRIKETHROUGH_MASK; metadata |= FontStyle.Strikethrough | MetadataConsts.STRIKETHROUGH_MASK;
break; break;
default:
if (typeof tokenStyle?.italic !== 'undefined') {
const italicbit = (tokenStyle?.italic ? FontStyle.Italic : 0);
metadata |= italicbit | MetadataConsts.ITALIC_MASK;
}
if (typeof tokenStyle?.bold !== 'undefined') {
const boldBit = (tokenStyle?.bold ? FontStyle.Bold : 0);
metadata |= boldBit | MetadataConsts.BOLD_MASK;
}
if (typeof tokenStyle?.underline !== 'undefined') {
const underlineBit = (tokenStyle?.underline ? FontStyle.Underline : 0);
metadata |= underlineBit | MetadataConsts.UNDERLINE_MASK;
}
if (typeof tokenStyle?.strikethrough !== 'undefined') {
const strikethroughBit = (tokenStyle?.strikethrough ? FontStyle.Strikethrough : 0);
metadata |= strikethroughBit | MetadataConsts.STRIKETHROUGH_MASK;
}
} }
const foreground = themeRule ? themeRule.settings.foreground : tokenStyle?.foreground; const foreground = tokenStyle?.foreground;
const tokenStyleForeground = foreground ? colorThemeData.getTokenColorIndex().get(foreground) : ColorId.DefaultForeground; const tokenStyleForeground = (foreground !== undefined) ? colorThemeData.getTokenColorIndex().get(foreground) : ColorId.DefaultForeground;
metadata |= tokenStyleForeground << MetadataConsts.FOREGROUND_OFFSET; metadata |= tokenStyleForeground << MetadataConsts.FOREGROUND_OFFSET;
return metadata; return metadata;

Просмотреть файл

@ -192,6 +192,9 @@ suite('Themes - TokenStyleResolving', () => {
tokenStyle = themeData.resolveScopes([['meta.structure.dictionary.json', 'string.quoted.double.json']]); tokenStyle = themeData.resolveScopes([['meta.structure.dictionary.json', 'string.quoted.double.json']]);
assertTokenStyle(tokenStyle, ts('#66D9EF', undefined), 'json property'); assertTokenStyle(tokenStyle, ts('#66D9EF', undefined), 'json property');
tokenStyle = themeData.resolveScopes([['source.json', 'meta.structure.dictionary.json', 'string.quoted.double.json']]);
assertTokenStyle(tokenStyle, ts('#66D9EF', undefined), 'json property');
tokenStyle = themeData.resolveScopes([['keyword'], ['storage.type'], ['entity.name.class']]); tokenStyle = themeData.resolveScopes([['keyword'], ['storage.type'], ['entity.name.class']]);
assertTokenStyle(tokenStyle, ts('#66D9EF', { italic: true, bold: false, underline: false }), 'storage.type'); assertTokenStyle(tokenStyle, ts('#66D9EF', { italic: true, bold: false, underline: false }), 'storage.type');

Просмотреть файл

@ -220,8 +220,8 @@ class TreeSitterTokenizationSupport extends Disposable implements ITreeSitterTok
// Check that the current token doesn't just replace the last token // Check that the current token doesn't just replace the last token
if ((previousTokenStartOffset + currentTokenLength) === originalPreviousTokenEndOffset) { if ((previousTokenStartOffset + currentTokenLength) === originalPreviousTokenEndOffset) {
// Current token and previous token span the exact same characters // Current token and previous token span the exact same characters, replace the last scope
endOffsetsAndScopes[tokenIndex - 1].scopes.push(capture.name); endOffsetsAndScopes[tokenIndex - 1].scopes[endOffsetsAndScopes[tokenIndex - 1].scopes.length - 1] = capture.name;
} else { } else {
// The current token is within the previous token. Adjust the end of the previous token. // The current token is within the previous token. Adjust the end of the previous token.
endOffsetsAndScopes[tokenIndex - 1].endOffset = intermediateTokenOffset; endOffsetsAndScopes[tokenIndex - 1].endOffset = intermediateTokenOffset;