From 374a7e5696f1a7966c800c90c3fa79373a3dc92f Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Sun, 14 Feb 2021 09:58:51 -0500 Subject: [PATCH] enh(autodetect) tcl: improve autodetection (#2865) * enh(autodetect) tcl: fewer false positives on variables For languages with $ident and @ident style variables this attempts to prevent positives for $ident$ and @ident@ type expressions, which are likely something else entirely. - Improves TCL variable detection to be more explicit - Adds TCL variable detection tests * fix(tcl) Make regex UTF-8 compatible --- src/languages/tcl.js | 33 +++++++++++++++------ test/markup/pgsql/dollar_strings.expect.txt | 4 +-- test/markup/php/comments.expect.txt | 1 - test/markup/tcl/default.expect.txt | 18 +++++------ test/markup/tcl/variables.expect.txt | 24 +++++++++++++++ test/markup/tcl/variables.txt | 24 +++++++++++++++ 6 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 test/markup/tcl/variables.expect.txt create mode 100644 test/markup/tcl/variables.txt diff --git a/src/languages/tcl.js b/src/languages/tcl.js index f1e0b0df31..3adcb34c91 100644 --- a/src/languages/tcl.js +++ b/src/languages/tcl.js @@ -5,7 +5,16 @@ Author: Radek Liska Website: https://www.tcl.tk/about/language.html */ +import * as regex from '../lib/regex.js'; + export default function(hljs) { + const TCL_IDENT = /[a-zA-Z_][a-zA-Z0-9_]*/; + + const NUMBER = { + className: 'number', + variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE] + }; + return { name: 'Tcl', aliases: ['tk'], @@ -39,15 +48,24 @@ export default function(hljs) { ] }, { - excludeEnd: true, + className: "variable", variants: [ { - begin: '\\$(\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\\(([a-zA-Z0-9_])*\\)', - end: '[^a-zA-Z0-9_\\}\\$]' + begin: regex.concat( + /\$/, + regex.optional(/::/), + TCL_IDENT, + '(::', + TCL_IDENT, + ')*' + ) }, { - begin: '\\$(\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*', - end: '(\\))?[^a-zA-Z0-9_\\}\\$]' + begin: '\\$\\{(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*', + end: '\\}', + contains: [ + NUMBER + ] } ] }, @@ -58,10 +76,7 @@ export default function(hljs) { hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}) ] }, - { - className: 'number', - variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE] - } + NUMBER ] } } diff --git a/test/markup/pgsql/dollar_strings.expect.txt b/test/markup/pgsql/dollar_strings.expect.txt index 978866a3a5..cf30a759bb 100644 --- a/test/markup/pgsql/dollar_strings.expect.txt +++ b/test/markup/pgsql/dollar_strings.expect.txt @@ -5,5 +5,5 @@ $$ $$ language sql STRICT; -SELECT sql_expression($sql$SELECT hello_world($phrase$Regina's elephant's dog$phrase$) - || $phrase$ I made a cat's meow today.$phrase$ $sql$); +SELECT sql_expression($sql$SELECT hello_world($phrase$Regina's elephant's dog$phrase$) + || $phrase$ I made a cat's meow today.$phrase$ $sql$); diff --git a/test/markup/php/comments.expect.txt b/test/markup/php/comments.expect.txt index c477b66da6..fbbcbb1468 100644 --- a/test/markup/php/comments.expect.txt +++ b/test/markup/php/comments.expect.txt @@ -17,4 +17,3 @@ function isOdd($a) { return ($a % 2) === 1; } - diff --git a/test/markup/tcl/default.expect.txt b/test/markup/tcl/default.expect.txt index 2d12c9ee86..717586adbb 100644 --- a/test/markup/tcl/default.expect.txt +++ b/test/markup/tcl/default.expect.txt @@ -5,22 +5,22 @@ set ::rand 4 proc give::recursive::count {base p} { ; # 2 mandatory params - while {$p > 0} { - set result [expr $result * $base]; incr p -1 + while {$p > 0} { + set result [expr $result * $base]; incr p -1 } - return $result + return $result } set a {a}; set b "bcdef"; set lst [list "item"] -puts [llength $a$b] +puts [llength $a$b] -set ::my::tid($id) $::my::tid(def) -lappend lst $arr($idx) $::my::arr($idx) $ar(key) -lreplace ::my::tid($id) 4 4 -puts $::rand ${::rand} ${::AWESOME::component::variable} +set ::my::tid($id) $::my::tid(def) +lappend lst $arr($idx) $::my::arr($idx) $ar(key) +lreplace ::my::tid($id) 4 4 +puts $::rand ${::rand} ${::AWESOME::component::variable} puts "$x + $y is\t [expr $x + $y]" proc isprime x { - expr {$x>1 && ![regexp {^(oo+?)\1+$} [string repeat o $x]]} + expr {$x>1 && ![regexp {^(oo+?)\1+$} [string repeat o $x]]} } diff --git a/test/markup/tcl/variables.expect.txt b/test/markup/tcl/variables.expect.txt new file mode 100644 index 0000000000..e963e216f0 --- /dev/null +++ b/test/markup/tcl/variables.expect.txt @@ -0,0 +1,24 @@ +$name +${name} +${::name} +${::namespace::name} +${::namespace::another::name} + +$name() +$name(32) +$name(index) + +$with_underscore::oth_er::and_finally(32) + +${name()} +${name(32)} +${name(index)} + +${ns::other::name()} +${ns::other::name(32)} +${ns::other::name(index)} + + +$ns::other::name() +$ns::other::name(32) +$ns::other::name(index) diff --git a/test/markup/tcl/variables.txt b/test/markup/tcl/variables.txt new file mode 100644 index 0000000000..9b17664761 --- /dev/null +++ b/test/markup/tcl/variables.txt @@ -0,0 +1,24 @@ +$name +${name} +${::name} +${::namespace::name} +${::namespace::another::name} + +$name() +$name(32) +$name(index) + +$with_underscore::oth_er::and_finally(32) + +${name()} +${name(32)} +${name(index)} + +${ns::other::name()} +${ns::other::name(32)} +${ns::other::name(index)} + + +$ns::other::name() +$ns::other::name(32) +$ns::other::name(index)