From 5f0770db54c05d77989abcfd786065a0d7922ece Mon Sep 17 00:00:00 2001 From: ahmedneilhussain Date: Fri, 21 Jun 2024 15:17:57 +0100 Subject: [PATCH] Semantic Tokens: Do not use default theme (#1029) Fix for https://github.com/eclipse/lsp4e/issues/1028 - we requested the default theme if no TM mapping for the editor, but this calls syncExec. Reconciler threads mustn't block on the UI thread as it is possible for the UI thread to be blocked waiting for reconciliation; this deadlock was indeed observed. --- org.eclipse.lsp4e.test/META-INF/MANIFEST.MF | 2 +- org.eclipse.lsp4e.test/fragment.xml | 30 + org.eclipse.lsp4e.test/pom.xml | 2 +- ...manticHighlightReconcilerStrategyTest.java | 24 +- .../test/semanticTokens/rust.tmLanguage.json | 692 ++++++++++++++++++ org.eclipse.lsp4e/META-INF/MANIFEST.MF | 4 +- .../semanticTokens/TokenTypeMapper.java | 4 +- 7 files changed, 746 insertions(+), 12 deletions(-) create mode 100644 org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/rust.tmLanguage.json diff --git a/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF b/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF index b5bb922b1..959010f52 100644 --- a/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for language server bundle (Incubation) Bundle-SymbolicName: org.eclipse.lsp4e.test;singleton:=true -Bundle-Version: 0.15.13.qualifier +Bundle-Version: 0.15.14.qualifier Fragment-Host: org.eclipse.lsp4e Bundle-Vendor: Eclipse.org Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/org.eclipse.lsp4e.test/fragment.xml b/org.eclipse.lsp4e.test/fragment.xml index 1006df833..2d6047a8f 100644 --- a/org.eclipse.lsp4e.test/fragment.xml +++ b/org.eclipse.lsp4e.test/fragment.xml @@ -43,6 +43,10 @@ contentType="org.eclipse.lsp4e.test.content-type" id="org.eclipse.lsp4e.test.server"> + + @@ -125,6 +129,13 @@ id="org.eclipse.lsp4e.test.content-type" name="Test Content Type" priority="normal"> + + + + + + + + + + + + + diff --git a/org.eclipse.lsp4e.test/pom.xml b/org.eclipse.lsp4e.test/pom.xml index eba1b961c..5149165f6 100644 --- a/org.eclipse.lsp4e.test/pom.xml +++ b/org.eclipse.lsp4e.test/pom.xml @@ -8,7 +8,7 @@ org.eclipse.lsp4e.test eclipse-test-plugin - 0.15.13-SNAPSHOT + 0.15.14-SNAPSHOT diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java index d7642f0cb..42fa68ff4 100644 --- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java @@ -49,7 +49,7 @@ public void testKeyword() throws CoreException { MockLanguageServer.INSTANCE.getTextDocumentService().setSemanticTokens(semanticTokens); - IFile file = TestUtils.createUniqueTestFile(project, "lspt", SemanticTokensTestUtil.keywordText); + IFile file = TestUtils.createUniqueTestFile(project, "lsptm", SemanticTokensTestUtil.keywordText); ITextViewer textViewer = TestUtils.openTextViewer(file); Display display = shell.getDisplay(); @@ -58,18 +58,30 @@ public void testKeyword() throws CoreException { StyleRange[] styleRanges = textViewer.getTextWidget().getStyleRanges(); var backgroundColor = textViewer.getTextWidget().getBackground(); - assertEquals(3, styleRanges.length); + assertEquals(6, styleRanges.length); assertEquals(0, styleRanges[0].start); assertEquals(4, styleRanges[0].length); assertNotEquals(styleRanges[0].foreground, backgroundColor); - assertEquals(15, styleRanges[1].start); - assertEquals(4, styleRanges[1].length); + assertEquals(4, styleRanges[1].start); + assertEquals(11, styleRanges[1].length); assertNotEquals(styleRanges[1].foreground, backgroundColor); - assertEquals(24, styleRanges[2].start); - assertEquals(7, styleRanges[2].length); + assertEquals(15, styleRanges[2].start); + assertEquals(4, styleRanges[2].length); assertNotEquals(styleRanges[2].foreground, backgroundColor); + + assertEquals(19, styleRanges[3].start); + assertEquals(5, styleRanges[3].length); + assertNotEquals(styleRanges[3].foreground, backgroundColor); + + assertEquals(24, styleRanges[4].start); + assertEquals(7, styleRanges[4].length); + assertNotEquals(styleRanges[4].foreground, backgroundColor); + + assertEquals(31, styleRanges[5].start); + assertEquals(11, styleRanges[5].length); + assertNotEquals(styleRanges[5].foreground, backgroundColor); } } diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/rust.tmLanguage.json b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/rust.tmLanguage.json new file mode 100644 index 000000000..0061937a0 --- /dev/null +++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/rust.tmLanguage.json @@ -0,0 +1,692 @@ +{ + "information_for_contributors": [ + "This file has been converted from https://github.com/zargony/atom-language-rust/blob/master/grammars/rust.cson", + "If you want to provide a fix or improvement, please create a pull request against the original repository.", + "Once accepted there, we are happy to receive an update request." + ], + "version": "https://github.com/zargony/atom-language-rust/commit/7d59e2ad79fbe5925bd2fd3bd3857bf9f421ff6f", + "name": "Definitely not rust", + "scopeName": "source.lsptm", + "patterns": [ + { + "comment": "Implementation", + "begin": "\\b(impl)\\b", + "end": "\\{", + "beginCaptures": { + "1": { + "name": "storage.type.rust" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#mut" + }, + { + "include": "#dyn" + }, + { + "include": "#ref_lifetime" + }, + { + "include": "#core_types" + }, + { + "include": "#core_marker" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_types" + }, + { + "include": "#std_traits" + }, + { + "include": "#type_params" + }, + { + "include": "#where" + }, + { + "name": "storage.type.rust", + "match": "\\bfor\\b" + }, + { + "include": "#type" + } + ] + }, + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + }, + { + "include": "#line_doc_comment" + }, + { + "include": "#line_comment" + }, + { + "comment": "Attribute", + "name": "meta.attribute.rust", + "begin": "#\\!?\\[", + "end": "\\]", + "patterns": [ + { + "include": "#string_literal" + }, + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + }, + { + "include": "#line_doc_comment" + }, + { + "include": "#line_comment" + } + ] + }, + { + "comment": "Single-quote string literal (character)", + "name": "string.quoted.single.rust", + "match": "b?'([^'\\\\]|\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.))'" + }, + { + "include": "#string_literal" + }, + { + "include": "#raw_string_literal" + }, + { + "comment": "Floating point literal (fraction)", + "name": "constant.numeric.float.rust", + "match": "\\b[0-9][0-9_]*\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\b" + }, + { + "comment": "Floating point literal (exponent)", + "name": "constant.numeric.float.rust", + "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\b" + }, + { + "comment": "Floating point literal (typed)", + "name": "constant.numeric.float.rust", + "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\b" + }, + { + "comment": "Integer literal (decimal)", + "name": "constant.numeric.integer.decimal.rust", + "match": "\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\b" + }, + { + "comment": "Integer literal (hexadecimal)", + "name": "constant.numeric.integer.hexadecimal.rust", + "match": "\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\b" + }, + { + "comment": "Integer literal (octal)", + "name": "constant.numeric.integer.octal.rust", + "match": "\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\b" + }, + { + "comment": "Integer literal (binary)", + "name": "constant.numeric.integer.binary.rust", + "match": "\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\b" + }, + { + "comment": "Static storage modifier", + "name": "storage.modifier.static.rust", + "match": "\\bstatic\\b" + }, + { + "comment": "Boolean constant", + "name": "constant.language.boolean.rust", + "match": "\\b(true|false)\\b" + }, + { + "comment": "Control keyword", + "name": "keyword.control.rust", + "match": "\\b(async|await|break|continue|else|if|in|for|loop|match|return|try|while)\\b" + }, + { + "comment": "Keyword", + "name": "keyword.other.rust", + "match": "\\b(crate|extern|mod|let|ref|use|super|move)\\b" + }, + { + "comment": "Reserved keyword", + "name": "invalid.deprecated.rust", + "match": "\\b(abstract|alignof|become|do|final|macro|offsetof|override|priv|proc|pure|sizeof|typeof|virtual|yield)\\b" + }, + { + "include": "#unsafe" + }, + { + "include": "#sigils" + }, + { + "include": "#self" + }, + { + "include": "#mut" + }, + { + "include": "#dyn" + }, + { + "include": "#impl" + }, + { + "include": "#box" + }, + { + "include": "#lifetime" + }, + { + "include": "#ref_lifetime" + }, + { + "include": "#const" + }, + { + "include": "#pub" + }, + { + "comment": "Miscellaneous operator", + "name": "keyword.operator.misc.rust", + "match": "(=>|::|\\bas\\b)" + }, + { + "comment": "Comparison operator", + "name": "keyword.operator.comparison.rust", + "match": "(&&|\\|\\||==|!=)" + }, + { + "comment": "Assignment operator", + "name": "keyword.operator.assignment.rust", + "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)" + }, + { + "comment": "Arithmetic operator", + "name": "keyword.operator.arithmetic.rust", + "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)" + }, + { + "comment": "Comparison operator (second group because of regex precedence)", + "name": "keyword.operator.comparison.rust", + "match": "(<=|>=|<|>)" + }, + { + "include": "#core_types" + }, + { + "include": "#core_vars" + }, + { + "include": "#core_marker" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_types" + }, + { + "include": "#std_traits" + }, + { + "comment": "Built-in macro", + "name": "support.function.builtin.rust", + "match": "\\b(macro_rules|compile_error|format_args|env|option_env|concat_idents|concat|line|column|file|stringify|include|include_str|include_bytes|module_path|cfg)!" + }, + { + "comment": "Core macro", + "name": "support.function.core.rust", + "match": "\\b(panic|assert|assert_eq|assert_ne|debug_assert|debug_assert_eq|debug_assert_ne|try|write|writeln|unreachable|unimplemented)!" + }, + { + "comment": "Standard library macro", + "name": "support.function.std.rust", + "match": "\\b(format|print|println|eprint|eprintln|select|vec)!" + }, + { + "comment": "Logging macro", + "name": "support.function.log.rust", + "match": "\\b(log|error|warn|info|debug|trace|log_enabled)!" + }, + { + "comment": "Invokation of a macro", + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\!)\\s*[({\\[]", + "captures": { + "1": { + "name": "entity.name.function.macro.rust" + } + } + }, + { + "comment": "Function call", + "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(", + "captures": { + "1": { + "name": "entity.name.function.rust" + } + } + }, + { + "comment": "Function call with type parameters", + "begin": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*(::)(?=\\s*<.*>\\s*\\()", + "end": "\\(", + "captures": { + "1": { + "name": "entity.name.function.rust" + }, + "2": { + "name": "keyword.operator.misc.rust" + } + }, + "patterns": [ + { + "include": "#type_params" + } + ] + }, + { + "comment": "Function definition", + "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)", + "end": "[\\{;]", + "beginCaptures": { + "1": { + "name": "keyword.other.fn.rust" + }, + "2": { + "name": "entity.name.function.rust" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#self" + }, + { + "include": "#mut" + }, + { + "include": "#dyn" + }, + { + "include": "#impl" + }, + { + "include": "#ref_lifetime" + }, + { + "include": "#core_types" + }, + { + "include": "#core_marker" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_types" + }, + { + "include": "#std_traits" + }, + { + "include": "#type_params" + }, + { + "include": "#const" + }, + { + "include": "#where" + }, + { + "include": "#unsafe" + }, + { + "comment": "Function arguments", + "match": "\bfn\b", + "name": "keyword.other.fn.rust" + } + ] + }, + { + "comment": "Type declaration", + "begin": "\\b(enum|struct|trait|union)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "end": "[\\{\\(;]", + "beginCaptures": { + "1": { + "name": "storage.type.rust" + }, + "2": { + "name": "entity.name.type.rust" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_traits" + }, + { + "include": "#type_params" + }, + { + "include": "#core_types" + }, + { + "include": "#pub" + }, + { + "include": "#where" + } + ] + }, + { + "comment": "Type alias", + "begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "end": ";", + "beginCaptures": { + "1": { + "name": "storage.type.rust" + }, + "2": { + "name": "entity.name.type.rust" + } + }, + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#mut" + }, + { + "include": "#dyn" + }, + { + "include": "#impl" + }, + { + "include": "#lifetime" + }, + { + "include": "#ref_lifetime" + }, + { + "include": "#core_types" + }, + { + "include": "#core_marker" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_types" + }, + { + "include": "#std_traits" + }, + { + "include": "#type_params" + } + ] + } + ], + "repository": { + "block_doc_comment": { + "comment": "Block documentation comment", + "name": "comment.block.documentation.rust", + "begin": "/\\*[\\*!](?![\\*/])", + "end": "\\*/", + "patterns": [ + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + } + ] + }, + "block_comment": { + "comment": "Block comment", + "name": "comment.block.rust", + "begin": "/\\*", + "end": "\\*/", + "patterns": [ + { + "include": "#block_doc_comment" + }, + { + "include": "#block_comment" + } + ] + }, + "line_doc_comment": { + "comment": "Single-line documentation comment", + "name": "comment.line.documentation.rust", + "begin": "//[!/](?=[^/])", + "end": "$" + }, + "line_comment": { + "comment": "Single-line comment", + "name": "comment.line.double-slash.rust", + "begin": "//", + "end": "$" + }, + "escaped_character": { + "name": "constant.character.escape.rust", + "match": "\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)" + }, + "string_literal": { + "comment": "Double-quote string literal", + "name": "string.quoted.double.rust", + "begin": "b?\"", + "end": "\"", + "patterns": [ + { + "include": "#escaped_character" + } + ] + }, + "raw_string_literal": { + "comment": "Raw double-quote string literal", + "name": "string.quoted.double.raw.rust", + "begin": "b?r(#*)\"", + "end": "\"\\1" + }, + "sigils": { + "comment": "Sigil", + "name": "keyword.operator.sigil.rust", + "match": "[&*](?=[a-zA-Z0-9_\\(\\[\\|\\\"]+)" + }, + "self": { + "comment": "Self variable", + "name": "variable.language.rust", + "match": "\\bself\\b" + }, + "mut": { + "comment": "Mutable storage modifier", + "name": "storage.modifier.mut.rust", + "match": "\\bmut\\b" + }, + "dyn": { + "comment": "Dynamic modifier", + "name": "storage.modifier.dyn.rust", + "match": "\\bdyn\\b" + }, + "impl": { + "comment": "Existential type modifier", + "name": "storage.modifier.impl.rust", + "match": "\\bimpl\\b" + }, + "box": { + "comment": "Box storage modifier", + "name": "storage.modifier.box.rust", + "match": "\\bbox\\b" + }, + "const": { + "comment": "Const storage modifier", + "name": "storage.modifier.const.rust", + "match": "\\bconst\\b" + }, + "pub": { + "comment": "Visibility modifier", + "name": "storage.modifier.visibility.rust", + "match": "\\bpub\\b" + }, + "unsafe": { + "comment": "Unsafe code keyword", + "name": "keyword.other.unsafe.rust", + "match": "\\bunsafe\\b" + }, + "where": { + "comment": "Generic where clause", + "name": "keyword.other.where.rust", + "match": "\\bwhere\\b" + }, + "lifetime": { + "comment": "Named lifetime", + "name": "storage.modifier.lifetime.rust", + "match": "'([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "captures": { + "1": { + "name": "entity.name.lifetime.rust" + } + } + }, + "ref_lifetime": { + "comment": "Reference with named lifetime", + "match": "&('([a-zA-Z_][a-zA-Z0-9_]*))\\b", + "captures": { + "1": { + "name": "storage.modifier.lifetime.rust" + }, + "2": { + "name": "entity.name.lifetime.rust" + } + } + }, + "core_types": { + "comment": "Built-in/core type", + "name": "storage.type.core.rust", + "match": "\\b(bool|char|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64|str|Self|Option|Result)\\b" + }, + "core_vars": { + "comment": "Core type variant", + "name": "support.constant.core.rust", + "match": "\\b(Some|None|Ok|Err)\\b" + }, + "core_marker": { + "comment": "Core trait (marker)", + "name": "support.type.marker.rust", + "match": "\\b(Copy|Send|Sized|Sync)\\b" + }, + "core_traits": { + "comment": "Core trait", + "name": "support.type.core.rust", + "match": "\\b(Drop|Fn|FnMut|FnOnce|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator)\\b" + }, + "std_types": { + "comment": "Standard library type", + "name": "storage.class.std.rust", + "match": "\\b(Box|String|Vec|Path|PathBuf)\\b" + }, + "std_traits": { + "comment": "Standard library trait", + "name": "support.type.std.rust", + "match": "\\b(ToOwned|ToString)\\b" + }, + "type": { + "comment": "A type", + "name": "entity.name.type.rust", + "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b" + }, + "type_params": { + "comment": "Type parameters", + "name": "meta.type_params.rust", + "begin": "<(?![=<])", + "end": "(?", + "patterns": [ + { + "include": "#block_comment" + }, + { + "include": "#line_comment" + }, + { + "include": "#sigils" + }, + { + "include": "#mut" + }, + { + "include": "#dyn" + }, + { + "include": "#impl" + }, + { + "include": "#lifetime" + }, + { + "include": "#core_types" + }, + { + "include": "#core_marker" + }, + { + "include": "#core_traits" + }, + { + "include": "#std_types" + }, + { + "include": "#std_traits" + }, + { + "include": "#type_params" + } + ] + } + } +} \ No newline at end of file diff --git a/org.eclipse.lsp4e/META-INF/MANIFEST.MF b/org.eclipse.lsp4e/META-INF/MANIFEST.MF index 77b4cca30..95b0bb511 100644 --- a/org.eclipse.lsp4e/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e/META-INF/MANIFEST.MF @@ -32,8 +32,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0", org.eclipse.ui.navigator;bundle-version="3.6.100", org.eclipse.lsp4j;bundle-version="[0.23.0,0.24.0)", org.eclipse.lsp4j.jsonrpc;bundle-version="[0.23.0,0.24.0)", - org.eclipse.mylyn.wikitext;bundle-version="4.2.0", - org.eclipse.mylyn.wikitext.markdown;bundle-version="4.2.0", + org.eclipse.mylyn.wikitext;bundle-version="4.3.0", + org.eclipse.mylyn.wikitext.markdown;bundle-version="4.3.0", org.eclipse.ui.console, org.eclipse.ltk.core.refactoring, org.eclipse.core.expressions;bundle-version="3.5.0", diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/semanticTokens/TokenTypeMapper.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/semanticTokens/TokenTypeMapper.java index 2a6ee0d60..9ba6e714f 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/semanticTokens/TokenTypeMapper.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/semanticTokens/TokenTypeMapper.java @@ -14,7 +14,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.rules.IToken; -import org.eclipse.tm4e.ui.TMUIPlugin; import org.eclipse.tm4e.ui.text.TMPresentationReconciler; import org.eclipse.tm4e.ui.themes.ITokenProvider; @@ -42,6 +41,7 @@ public IToken apply(final String tokenType) { return tokenProvider.getToken(tokenType); } } - return TMUIPlugin.getThemeManager().getDefaultTheme().getToken(tokenType); + // No mapping if no TextMate grammar associated with this content type + return null; } }