From 9587ba1802a255c5a4f705ec704c68867d5407a9 Mon Sep 17 00:00:00 2001 From: Leitwolf11 Date: Fri, 9 Oct 2026 23:16:07 +0300 Subject: [PATCH] Tokenize the method reference sign of Visual X# Visual X# 0.5.0 implements the method reference `Type::Method`, and its lexer has `::` as one sign. The tokenizer that colours Visual X# listed the compiler's signs without it, so the reference was two colons of punctuation. `::` is now an operator of the list, ahead of the single colon, as in the compiler. The tests hold a reference between two names, a reference whose type is written through its namespace, that a single colon is still the punctuation of a conditional, and a conditional that selects strings. --- .../xide/syntax/VisualXSharpTokenizer.kt | 5 ++-- .../xide/syntax/VisualXSharpTokenizerTest.kt | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/modules/syntax/src/main/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizer.kt b/modules/syntax/src/main/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizer.kt index 50f8512..2a2f010 100644 --- a/modules/syntax/src/main/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizer.kt +++ b/modules/syntax/src/main/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizer.kt @@ -16,7 +16,8 @@ package com.progmasoft.xide.syntax * - a comment whose text starts with `|` or `!` is a documentation comment; * - `[[` and `[=[` start a raw string with the same long-bracket rule, in which nothing is an escape; * - a quoted string may continue over line breaks and has backslash escapes; - * - `'` separates digit groups inside a number and otherwise starts a character literal. + * - `'` separates digit groups inside a number and otherwise starts a character literal; + * - `::` is one sign, the method reference of `Type::Method`, and not two colons. */ object VisualXSharpTokenizer : Tokenizer { /** The reserved words of the language, as the compiler's lexer lists them. */ @@ -32,7 +33,7 @@ object VisualXSharpTokenizer : Tokenizer { private val operators: List = listOf( "...", "<<=", ">>=", "**=", "//=", "??=", - "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "??", "?:", "==", "\\=", "<=", ">=", "&&", "||", "//", "->", + "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "??", "?:", "::", "==", "\\=", "<=", ">=", "&&", "||", "//", "->", "**", "++", "=", "+", "-", "*", "/", "%", "&", "|", "^", "<", ">", "!", "?", "\\", ) diff --git a/modules/syntax/src/test/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizerTest.kt b/modules/syntax/src/test/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizerTest.kt index 0d9ec51..90898ba 100644 --- a/modules/syntax/src/test/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizerTest.kt +++ b/modules/syntax/src/test/kotlin/com/progmasoft/xide/syntax/VisualXSharpTokenizerTest.kt @@ -126,6 +126,30 @@ class VisualXSharpTokenizerTest { tokenizer.assertPieces("!mask", O to "!", I to "mask") } + @Test + fun aMethodReferenceIsOneSignBetweenTwoNames() { + tokenizer.assertPieces( + "auto next = Counter::Next;", + K to "auto", I to "next", O to "=", I to "Counter", O to "::", I to "Next", P to ";", + ) + tokenizer.assertPieces( + "Apply(Demo.Counter::Next)", + I to "Apply", P to "(", I to "Demo", P to ".", I to "Counter", O to "::", I to "Next", P to ")", + ) + // One colon is still the punctuation of a conditional. + tokenizer.assertPieces("a ? b : c", I to "a", O to "?", I to "b", P to ":", I to "c") + tokenizer.assertPieces("a :: : b", I to "a", O to "::", P to ":", I to "b") + } + + @Test + fun aConditionalSelectsStrings() { + tokenizer.assertPieces( + "String kind = count > 0 ? \"some\" : \"none\";", + I to "String", I to "kind", O to "=", I to "count", O to ">", N to "0", O to "?", S to "\"some\"", + P to ":", S to "\"none\"", P to ";", + ) + } + @Test fun everyCompilerKeywordIsAKeyword() { for (keyword in VisualXSharpTokenizer.keywords) {