From d0bcd0741dd67df57c71aed7d3fe80c9395e246c Mon Sep 17 00:00:00 2001 From: Brian Egan Date: Wed, 17 Mar 2021 16:54:04 +0100 Subject: [PATCH] Dart: Improved support for classes & generics (#2810) --- components/prism-dart.js | 87 ++++++++++++++----- components/prism-dart.min.js | 2 +- tests/languages/dart/class-name_feature.test | 91 ++++++++++++++++++++ tests/languages/dart/keyword_feature.test | 6 +- tests/languages/dart/operator_feature.test | 16 ++-- 5 files changed, 167 insertions(+), 35 deletions(-) create mode 100644 tests/languages/dart/class-name_feature.test diff --git a/components/prism-dart.js b/components/prism-dart.js index cd4230a40d..0101e4640e 100644 --- a/components/prism-dart.js +++ b/components/prism-dart.js @@ -1,24 +1,67 @@ -Prism.languages.dart = Prism.languages.extend('clike', { - 'string': [ - { - pattern: /r?("""|''')[\s\S]*?\1/, - greedy: true - }, - { - pattern: /r?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, - greedy: true - } - ], - 'keyword': [ +(function (Prism) { + var keywords = [ /\b(?:async|sync|yield)\*/, - /\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|Function|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/ - ], - 'operator': /\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/ -}); + /\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/ + ]; + + // Handles named imports, such as http.Client + var packagePrefix = /(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source; + + // based on the dart naming conventions + var className = { + pattern: RegExp(packagePrefix + /[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source), + lookbehind: true, + inside: { + 'namespace': { + pattern: /^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/, + inside: { + 'punctuation': /\./ + } + }, + } + }; -Prism.languages.insertBefore('dart','function',{ - 'metadata': { - pattern: /@\w+/, - alias: 'symbol' - } -}); + Prism.languages.dart = Prism.languages.extend('clike', { + 'string': [ + { + pattern: /r?("""|''')[\s\S]*?\1/, + greedy: true + }, + { + pattern: /r?(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/, + greedy: true + } + ], + 'class-name': [ + className, + { + // variables and parameters + // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods) + pattern: RegExp(packagePrefix + /[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source), + lookbehind: true, + inside: className.inside + } + ], + 'keyword': keywords, + 'operator': /\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/ + }); + + Prism.languages.insertBefore('dart','function',{ + 'metadata': { + pattern: /@\w+/, + alias: 'symbol' + } + }); + + Prism.languages.insertBefore('dart','class-name',{ + 'generics': { + pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, + inside: { + 'class-name': className, + 'keyword': keywords, + 'punctuation': /[<>(),.:]/, + 'operator': /[?&|]/ + } + }, + }); +}(Prism)); diff --git a/components/prism-dart.min.js b/components/prism-dart.min.js index 1a6bfbd71f..03e935bdb4 100644 --- a/components/prism-dart.min.js +++ b/components/prism-dart.min.js @@ -1 +1 @@ -Prism.languages.dart=Prism.languages.extend("clike",{string:[{pattern:/r?("""|''')[\s\S]*?\1/,greedy:!0},{pattern:/r?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0}],keyword:[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|Function|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),Prism.languages.insertBefore("dart","function",{metadata:{pattern:/@\w+/,alias:"symbol"}}); \ No newline at end of file +!function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],t="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{string:[{pattern:/r?("""|''')[\s\S]*?\1/,greedy:!0},{pattern:/r?(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0}],"class-name":[s,{pattern:RegExp(t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","function",{metadata:{pattern:/@\w+/,alias:"symbol"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); \ No newline at end of file diff --git a/tests/languages/dart/class-name_feature.test b/tests/languages/dart/class-name_feature.test new file mode 100644 index 0000000000..f13f8cdb8b --- /dev/null +++ b/tests/languages/dart/class-name_feature.test @@ -0,0 +1,91 @@ +class Foo with ns.Bar { + const Foo(this.bar); + + final Bar bar; + + Baz baz(ns.Bat bat) { + return Baz(bat); + } + +} + +---------------------------------------------------- + +[ + ["keyword", "class"], + ["class-name", ["Foo"]], + ["keyword", "with"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bar" + ]], + ["punctuation", "{"], + + ["keyword", "const"], + ["class-name", ["Foo"]], + ["punctuation", "("], + ["keyword", "this"], + ["punctuation", "."], + "bar", + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "final"], + ["class-name", ["Bar"]], + " bar", + ["punctuation", ";"], + + ["class-name", ["Baz"]], + ["generics", [ + ["punctuation", "<"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + ["punctuation", ">"] + ]], + ["function", "baz"], + ["punctuation", "("], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + " bat", + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "return"], + ["class-name", [ + "Baz" + ]], + ["generics", [ + ["punctuation", "<"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + ["punctuation", ">"] + ]], + ["punctuation", "("], + "bat", + ["punctuation", ")"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks class names and generics diff --git a/tests/languages/dart/keyword_feature.test b/tests/languages/dart/keyword_feature.test index bc78ce3e11..745f75e9e8 100644 --- a/tests/languages/dart/keyword_feature.test +++ b/tests/languages/dart/keyword_feature.test @@ -7,7 +7,7 @@ continue covariant default deferred do dynamic else enum export extension external extends; -factory final finally for Function +factory final finally for get hide if implements; interface; @@ -34,7 +34,7 @@ void while with yield ["keyword", "do"], ["keyword", "dynamic"], ["keyword", "else"], ["keyword", "enum"], ["keyword", "export"], ["keyword", "extension"], ["keyword", "external"], ["keyword", "extends"], ["punctuation", ";"], - ["keyword", "factory"], ["keyword", "final"], ["keyword", "finally"], ["keyword", "for"], ["keyword", "Function"], + ["keyword", "factory"], ["keyword", "final"], ["keyword", "finally"], ["keyword", "for"], ["keyword", "get"], ["keyword", "hide"], ["keyword", "if"], ["keyword", "implements"], ["punctuation", ";"], ["keyword", "interface"], ["punctuation", ";"], @@ -51,4 +51,4 @@ void while with yield ---------------------------------------------------- -Checks for all keywords. \ No newline at end of file +Checks for all keywords. diff --git a/tests/languages/dart/operator_feature.test b/tests/languages/dart/operator_feature.test index 5d631fd0bb..01993d9ed4 100644 --- a/tests/languages/dart/operator_feature.test +++ b/tests/languages/dart/operator_feature.test @@ -1,14 +1,13 @@ ++ -- * / % ~/ + - ! ~ -<< >> ? -& ^ | ->= > <= < +< << <= <<= +> >> >= >>= +& ^ | ? as is is! == != && || = *= /= ~/= %= += -= -<<= >>= &= ^= |= ---------------------------------------------------- @@ -17,17 +16,16 @@ as is is! ["operator", "++"], ["operator", "--"], ["operator", "*"], ["operator", "/"], ["operator", "%"], ["operator", "~/"], ["operator", "+"], ["operator", "-"], ["operator", "!"], ["operator", "~"], - ["operator", "<<"], ["operator", ">>"], ["operator", "?"], - ["operator", "&"], ["operator", "^"], ["operator", "|"], - ["operator", ">="], ["operator", ">"], ["operator", "<="], ["operator", "<"], + ["operator", "<"], ["operator", "<<"], ["operator", "<="], ["operator", "<<="], + ["operator", ">"], ["operator", ">>"], ["operator", ">="], ["operator", ">>="], + ["operator", "&"], ["operator", "^"], ["operator", "|"], ["operator", "?"], ["operator", "as"], ["operator", "is"], ["operator", "is!"], ["operator", "=="], ["operator", "!="], ["operator", "&&"], ["operator", "||"], ["operator", "="], ["operator", "*="], ["operator", "/="], ["operator", "~/="], ["operator", "%="], ["operator", "+="], ["operator", "-="], - ["operator", "<<="], ["operator", ">>="], ["operator", "&="], ["operator", "^="], ["operator", "|="] ] ---------------------------------------------------- -Checks for all operators. \ No newline at end of file +Checks for all operators.