diff --git a/components/prism-cpp.js b/components/prism-cpp.js index cf14d49b64..55a2fae60e 100644 --- a/components/prism-cpp.js +++ b/components/prism-cpp.js @@ -1,6 +1,7 @@ (function (Prism) { - var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; + var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; + var modName = /\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g, function () { return keyword.source; }) Prism.languages.cpp = Prism.languages.extend('c', { 'class-name': [ @@ -31,6 +32,26 @@ }); Prism.languages.insertBefore('cpp', 'string', { + 'module': { + // https://en.cppreference.com/w/cpp/language/modules + pattern: RegExp( + /(\b(?:module|import)\s+)/.source + + '(?:' + + // header-name + /"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source + + '|' + + // module name or partition or both + /(?:\s*:\s*)?|:\s*/.source.replace(//g, function () { return modName; }) + + ')' + ), + lookbehind: true, + greedy: true, + inside: { + 'string': /^[<"][\s\S]+/, + 'operator': /:/, + 'punctuation': /\./ + } + }, 'raw-string': { pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, alias: 'string', diff --git a/components/prism-cpp.min.js b/components/prism-cpp.min.js index 7ab1f0d4ea..16f98cc5cc 100644 --- a/components/prism-cpp.min.js +++ b/components/prism-cpp.min.js @@ -1 +1 @@ -!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/;e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); \ No newline at end of file +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,function(){return n})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); \ No newline at end of file diff --git a/components/prism-elixir.js b/components/prism-elixir.js index cfad1c8841..868e1fc732 100644 --- a/components/prism-elixir.js +++ b/components/prism-elixir.js @@ -1,5 +1,15 @@ Prism.languages.elixir = { - 'comment': /#.*/m, + 'doc': { + pattern: /@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/, + inside: { + 'attribute': /^@\w+/, + 'string': /['"][\s\S]+/ + } + }, + 'comment': { + pattern: /#.*/m, + greedy: true + }, // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r 'regex': { pattern: /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/, @@ -36,14 +46,12 @@ Prism.languages.elixir = { lookbehind: true, alias: 'symbol' }, + 'module': { + pattern: /\b[A-Z]\w*\b/, + alias: 'class-name' + }, // Look-ahead prevents bad highlighting of the :: operator 'attr-name': /\w+\??:(?!:)/, - 'capture': { - // Look-behind prevents bad highlighting of the && operator - pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/, - lookbehind: true, - alias: 'function' - }, 'argument': { // Look-behind prevents bad highlighting of the && operator pattern: /(^|[^&])&\d+/, @@ -54,8 +62,9 @@ Prism.languages.elixir = { pattern: /@\w+/, alias: 'variable' }, + 'function': /\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d+))/, 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, - 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/, + 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|raise|require|rescue|try|unless|use|when)\b/, 'boolean': /\b(?:true|false|nil)\b/, 'operator': [ /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, @@ -73,18 +82,6 @@ Prism.languages.elixir = { 'punctuation': /<<|>>|[.,%\[\]{}()]/ }; -Prism.languages.insertBefore('elixir', 'keyword', { - 'module': { - pattern: /\b(defmodule\s)[A-Z][\w.\\]+/, - lookbehind: true, - alias: 'class-name' - }, - 'function': { - pattern: /\b(defp?\s)[\w.\\]+/, - lookbehind: true - } -}); - Prism.languages.elixir.string.forEach(function(o) { o.inside = { 'interpolation': { diff --git a/components/prism-elixir.min.js b/components/prism-elixir.min.js index ee6542e41f..83f6871ed9 100644 --- a/components/prism-elixir.min.js +++ b/components/prism-elixir.min.js @@ -1 +1 @@ -Prism.languages.elixir={comment:/#.*/m,regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},"attr-name":/\w+\??:(?!:)/,capture:{pattern:/(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,lookbehind:!0,alias:"function"},argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.insertBefore("elixir","keyword",{module:{pattern:/\b(defmodule\s)[A-Z][\w.\\]+/,lookbehind:!0,alias:"class-name"},function:{pattern:/\b(defp?\s)[\w.\\]+/,lookbehind:!0}}),Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}); \ No newline at end of file +Prism.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/m,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d+))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|raise|require|rescue|try|unless|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}); \ No newline at end of file diff --git a/components/prism-ini.js b/components/prism-ini.js index c7b45a8ba4..e950caf96a 100644 --- a/components/prism-ini.js +++ b/components/prism-ini.js @@ -1,11 +1,42 @@ Prism.languages.ini= { - 'comment': /^[ \t]*[;#].*$/m, - 'selector': /^[ \t]*\[.*?\]/m, - 'constant': /^[ \t]*[^\s=]+?(?=[ \t]*=)/m, - 'attr-value': { - pattern: /=.*/, + + /** + * The component mimics the behavior of the Win32 API parser. + * + * @see {@link https://github.com/PrismJS/prism/issues/2775#issuecomment-787477723} + */ + + 'comment': { + pattern: /(^[ \f\t\v]*)[#;][^\n\r]*/m, + lookbehind: true + }, + 'header': { + pattern: /(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m, + lookbehind: true, inside: { - 'punctuation': /^[=]/ + 'section-name': { + pattern: /(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/, + lookbehind: true, + alias: 'selector' + }, + 'punctuation': /\[|\]/ } - } + }, + 'key': { + pattern: /(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m, + lookbehind: true, + alias: 'attr-name' + }, + 'value': { + pattern: /(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/, + lookbehind: true, + alias: 'attr-value', + inside: { + 'inner-value': { + pattern: /^("|').+(?=\1$)/, + lookbehind: true + } + } + }, + 'punctuation': /=/ }; diff --git a/components/prism-ini.min.js b/components/prism-ini.min.js index 620cdb55b4..a4e2d8e09b 100644 --- a/components/prism-ini.min.js +++ b/components/prism-ini.min.js @@ -1 +1 @@ -Prism.languages.ini={comment:/^[ \t]*[;#].*$/m,selector:/^[ \t]*\[.*?\]/m,constant:/^[ \t]*[^\s=]+?(?=[ \t]*=)/m,"attr-value":{pattern:/=.*/,inside:{punctuation:/^[=]/}}}; \ No newline at end of file +Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},header:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}; \ No newline at end of file diff --git a/tests/languages/cpp/keyword_feature.test b/tests/languages/cpp/keyword_feature.test index ac72b6a31d..69c90b55df 100644 --- a/tests/languages/cpp/keyword_feature.test +++ b/tests/languages/cpp/keyword_feature.test @@ -33,20 +33,24 @@ enum; explicit export extern +final float for friend goto if +import; inline int long +module; mutable namespace new noexcept nullptr operator +override private protected public @@ -125,20 +129,24 @@ uint64_t ["keyword", "explicit"], ["keyword", "export"], ["keyword", "extern"], + ["keyword", "final"], ["keyword", "float"], ["keyword", "for"], ["keyword", "friend"], ["keyword", "goto"], ["keyword", "if"], + ["keyword", "import"], ["punctuation", ";"], ["keyword", "inline"], ["keyword", "int"], ["keyword", "long"], + ["keyword", "module"], ["punctuation", ";"], ["keyword", "mutable"], ["keyword", "namespace"], ["keyword", "new"], ["keyword", "noexcept"], ["keyword", "nullptr"], ["keyword", "operator"], + ["keyword", "override"], ["keyword", "private"], ["keyword", "protected"], ["keyword", "public"], diff --git a/tests/languages/cpp/module_feature.test b/tests/languages/cpp/module_feature.test new file mode 100644 index 0000000000..b6675c3d4e --- /dev/null +++ b/tests/languages/cpp/module_feature.test @@ -0,0 +1,116 @@ +export module speech; + +export const char* get_phrase_en() { + return "Hello, world!"; +} + +export module speech; + +export import :english; +export import :spanish; + +export module speech:english; + +import speech; +import :PrivWidget; + +import ; +import ; +import "foo.h"; +import ; + +module : private; + +---------------------------------------------------- + +[ + ["keyword", "export"], + ["keyword", "module"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "const"], + ["keyword", "char"], + ["operator", "*"], + ["function", "get_phrase_en"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "return"], + ["string", "\"Hello, world!\""], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["keyword", "export"], + ["keyword", "module"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "english" + ]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "spanish" + ]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "module"], + ["module", [ + "speech", + ["operator", ":"], + "english" + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "PrivWidget" + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", "\"foo.h\""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "module"], + ["operator", ":"], + ["keyword", "private"], + ["punctuation", ";"] +] \ No newline at end of file diff --git a/tests/languages/elixir/attribute_feature.test b/tests/languages/elixir/attribute_feature.test index 273c2a402f..52c0bc1c6d 100644 --- a/tests/languages/elixir/attribute_feature.test +++ b/tests/languages/elixir/attribute_feature.test @@ -8,12 +8,10 @@ foobar [ ["attribute", "@vsn"], ["number", "2"], - ["attribute", "@moduledoc"], ["string", [ - "\"\"\"\r\nfoobar\r\n\"\"\"" - ]], + ["doc", [ ["attribute", "@moduledoc" ], [ "string", "\"\"\"\r\nfoobar\r\n\"\"\"" ] ] ], ["attribute", "@tag"], ["atom", ":external"] ] ---------------------------------------------------- -Checks for module attributes. \ No newline at end of file +Checks for module attributes. diff --git a/tests/languages/elixir/capture_feature.test b/tests/languages/elixir/capture_feature.test index 8a64b66154..caa9473be9 100644 --- a/tests/languages/elixir/capture_feature.test +++ b/tests/languages/elixir/capture_feature.test @@ -1,28 +1,56 @@ +&Math.zero?(0) fun = &Math.zero?/1 (&is_function/1).(fun) fun = &(&1 + 1) &List.flatten(&1, &2) +fun = &Math.zero?/invalid + ---------------------------------------------------- [ - "fun ", ["operator", "="], - ["capture", "&Math.zero?/1"], + ["operator", "&"], + ["module", "Math"], + ["punctuation", "."], + ["function", "zero?" ], ["punctuation", "("], - ["capture", "&is_function/1"], + ["number", "0"], + ["punctuation", ")"], + "\r\nfun ", ["operator", "="], + ["operator", "&"], + ["module", "Math"], + ["punctuation", "."], + ["function", "zero?" ], + ["operator", "/"], + ["number", "1"], + ["punctuation", "("], + ["operator", "&"], + ["function", "is_function"], + ["operator", "/"], + ["number", "1"], ["punctuation", ")"], ["punctuation", "."], ["punctuation", "("], "fun", ["punctuation", ")"], "\r\nfun ", ["operator", "="], - ["capture", "&"], + ["operator", "&"], ["punctuation", "("], ["argument", "&1"], ["operator", "+"], ["number", "1"], ["punctuation", ")"], - ["capture", "&List.flatten"], + ["operator", "&"], + ["module", "List"], + ["punctuation", "."], ["function", "flatten"], ["punctuation", "("], ["argument", "&1"], ["punctuation", ","], ["argument", "&2"], - ["punctuation", ")"] + ["punctuation", ")"], + "\r\n\r\nfun ", + [ "operator", "=" ], + [ "operator", "&" ], + [ "module", "Math" ], + [ "punctuation", "." ], + "zero?", + [ "operator", "/" ], + "invalid" ] ---------------------------------------------------- -Checks for function capturing and arguments. \ No newline at end of file +Checks for function capturing and arguments. diff --git a/tests/languages/elixir/doc_feature.test b/tests/languages/elixir/doc_feature.test new file mode 100644 index 0000000000..27e8ceadbb --- /dev/null +++ b/tests/languages/elixir/doc_feature.test @@ -0,0 +1,56 @@ +@doc "single" +@doc 'single' +@doc """triple""" +@doc '''triple''' +@doc ''' +multiline +''' +@doc """ +multiline +""" +@doc since: "1.3.0" +@doc deprecated: "phased out" + +@moduledoc "single" +@moduledoc 'single' +@moduledoc """triple""" +@moduledoc '''triple''' +@moduledoc ''' +multiline +''' +@moduledoc """ +multiline +""" +@moduledoc since: "1.3.0" +@moduledoc deprecated: "phased out" + +---------------------------------------------------- + +[ + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"single\"" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'single'" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"\"\"triple\"\"\"" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'''triple'''" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'''\nmultiline\n'''" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"\"\"\nmultiline\n\"\"\"" ] ] ], + [ "attribute", "@doc" ], + [ "attr-name", "since:" ], + [ "string", [ "\"1.3.0\"" ] ], + [ "attribute", "@doc" ], + [ "attr-name", "deprecated:" ], + [ "string", [ "\"phased out\"" ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"single\"" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'single'" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"\"\"triple\"\"\"" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'''triple'''" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'''\nmultiline\n'''" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"\"\"\nmultiline\n\"\"\"" ] ] ], + [ "attribute", "@moduledoc" ], + [ "attr-name", "since:" ], + [ "string", [ "\"1.3.0\"" ] ], + [ "attribute", "@moduledoc" ], + [ "attr-name", "deprecated:" ], + [ "string", [ "\"phased out\"" ] ] +] + +---------------------------------------------------- diff --git a/tests/languages/elixir/issue1392.test b/tests/languages/elixir/issue1392.test index c7d20a8366..1c0c93b3aa 100644 --- a/tests/languages/elixir/issue1392.test +++ b/tests/languages/elixir/issue1392.test @@ -3,9 +3,9 @@ String.upcase(@fixed) ---------------------------------------------------- [ - "String", + ["module", "String"], ["punctuation", "."], - "upcase", + ["function", "upcase"], ["punctuation", "("], ["attribute", "@fixed"], ["punctuation", ")"] @@ -13,4 +13,4 @@ String.upcase(@fixed) ---------------------------------------------------- -Ensure module attributes don't consume punctuation. \ No newline at end of file +Ensure module attributes don't consume punctuation. diff --git a/tests/languages/elixir/issue775.test b/tests/languages/elixir/issue775.test index d3243f80a8..9804bba6d9 100644 --- a/tests/languages/elixir/issue775.test +++ b/tests/languages/elixir/issue775.test @@ -5,13 +5,16 @@ ---------------------------------------------------- [ - ["attribute", "@doc"], - ["string", [ - "\"\"\"\r\n## Parameters\r\n\"\"\"" - ]] + [ + "doc", + [ + [ "attribute", "@doc" ], + [ "string", "\"\"\"\r\n## Parameters\r\n\"\"\"" ] + ] + ] ] ---------------------------------------------------- Ensures that markdown headers are not highlighted as comments inside strings. -See #775 for details. \ No newline at end of file +See #775 for details. diff --git a/tests/languages/elixir/keyword_feature.test b/tests/languages/elixir/keyword_feature.test index 6a851f1b24..c4f56fed67 100644 --- a/tests/languages/elixir/keyword_feature.test +++ b/tests/languages/elixir/keyword_feature.test @@ -9,7 +9,7 @@ defdelegate defstruct do else end fn for if import not or -require rescue try +raise require rescue try unless use when ---------------------------------------------------- @@ -26,7 +26,7 @@ unless use when ["keyword", "defstruct"], ["keyword", "do"], ["keyword", "else"], ["keyword", "end"], ["keyword", "fn"], ["keyword", "for"], ["keyword", "if"], ["keyword", "import"], ["keyword", "not"], ["keyword", "or"], - ["keyword", "require"], ["keyword", "rescue"], ["keyword", "try"], + ["keyword", "raise"], ["keyword", "require"], ["keyword", "rescue"], ["keyword", "try"], ["keyword", "unless"], ["keyword", "use"], ["keyword", "when"] ] diff --git a/tests/languages/ini/comment_feature.test b/tests/languages/ini/comment_feature.test index 30e373c63a..48e1d39db0 100644 --- a/tests/languages/ini/comment_feature.test +++ b/tests/languages/ini/comment_feature.test @@ -1,15 +1,50 @@ -; -; foobar -# foobar - ----------------------------------------------------- - -[ - ["comment", ";"], - ["comment", "; foobar"], - ["comment", "# foobar"] -] - ----------------------------------------------------- - -Checks for comments. + # + ; + # + ; +# +# +# +#; +#[foo] +#foo=bar +#foobar +; +; +; +;# +;[foo] +;foo=bar +;foobar +foo#bar +foobar# +foo;bar +foobar; + +---------------------------------------------------- + +[ + ["comment", "#"], + ["comment", ";"], + ["comment", "#"], + ["comment", ";"], + ["comment", "#"], + ["comment", "#\t"], + ["comment", "# "], + ["comment", "#;"], + ["comment", "#[foo]"], + ["comment", "#foo=bar"], + ["comment", "#foobar"], + ["comment", ";"], + ["comment", ";\t"], + ["comment", "; "], + ["comment", ";#"], + ["comment", ";[foo]"], + ["comment", ";foo=bar"], + ["comment", ";foobar"], + "\nfoo#bar\nfoobar#\nfoo;bar\nfoobar;" +] + +---------------------------------------------------- + +Checks for comments. diff --git a/tests/languages/ini/header_feature.test b/tests/languages/ini/header_feature.test new file mode 100644 index 0000000000..9f0df51ac4 --- /dev/null +++ b/tests/languages/ini/header_feature.test @@ -0,0 +1,86 @@ + [foo1] +[ "foo2" ] +[ foo3 ] +[" foo4 "] +["foo5 bar5"] +["foo6"] +[foo7 +[foo8 bar8] +[foo9[bar9] +[foo10] +[foo11]bar11] + +---------------------------------------------------- + +[ + ["header", [ + ["punctuation", "["], + ["section-name", "foo1"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo2\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo3"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\" foo4 \""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo5 bar5\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo6\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo7"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo8 bar8"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo9[bar9"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo10"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo11"], + ["punctuation", "]"] + ]], + + "bar11]" +] + +---------------------------------------------------- + +Checks for headers (and section names). diff --git a/tests/languages/ini/key_value_feature.test b/tests/languages/ini/key_value_feature.test index 5d25d9d3cf..f39988bd45 100644 --- a/tests/languages/ini/key_value_feature.test +++ b/tests/languages/ini/key_value_feature.test @@ -1,21 +1,69 @@ -foo=Bar Baz -foobar=42 - ----------------------------------------------------- - -[ - ["constant", "foo"], - ["attr-value", [ - ["punctuation", "="], - "Bar Baz" - ]], - ["constant", "foobar"], - ["attr-value", [ - ["punctuation", "="], - "42" - ]] -] - ----------------------------------------------------- - -Checks for key/value pairs. \ No newline at end of file + bar1 = + "bar2" = + 'bar3' = + bar4 = +" bar5 "= +"bar6"= +' bar7 '= +'bar8'= += baz9 += "baz10" += 'baz11' += baz12 +=" baz13 " +="b14"a14"z14" +="baz15" +="baz16 +=' baz17 ' +='baz18' +=b19"a19"z19 +=b20"az20 +=ba21"z21 +=baz22 +=baz23" +bar24 +bar25 baz25=qux25 +bar26= +bar27==baz27 +bar28=baz28 +bar29=baz29 qux29 +bar30=baz30=qux30 + +---------------------------------------------------- + +[ + ["key", "bar1"], ["punctuation", "="], + ["key", "\"bar2\""], ["punctuation", "="], + ["key", "'bar3'"], ["punctuation", "="], + ["key", "bar4"], ["punctuation", "="], + ["key", "\" bar5 \""], ["punctuation", "="], + ["key", "\"bar6\""], ["punctuation", "="], + ["key", "' bar7 '"], ["punctuation", "="], + ["key", "'bar8'"], ["punctuation", "="], + ["punctuation", "="], ["value", ["baz9"]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "baz10"], "\""]], + ["punctuation", "="], ["value", ["'", ["inner-value", "baz11"], "'"]], + ["punctuation", "="], ["value", ["baz12"]], + ["punctuation", "="], ["value", ["\"", ["inner-value", " baz13 "], "\""]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "b14\"a14\"z14"], "\""]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "baz15"], "\""]], + ["punctuation", "="], ["value", ["\"baz16"]], + ["punctuation", "="], ["value", ["'", ["inner-value", " baz17 "], "'"]], + ["punctuation", "="], ["value", ["'", ["inner-value", "baz18"], "'"]], + ["punctuation", "="], ["value", ["b19\"a19\"z19"]], + ["punctuation", "="], ["value", ["b20\"az20"]], + ["punctuation", "="], ["value", ["ba21\"z21"]], + ["punctuation", "="], ["value", ["baz22"]], + ["punctuation", "="], ["value", ["baz23\""]], + "\nbar24\n", + ["key", "bar25 baz25"], ["punctuation", "="], ["value", ["qux25"]], + ["key", "bar26"], ["punctuation", "="], + ["key", "bar27"], ["punctuation", "="], ["value", ["=baz27"]], + ["key", "bar28"], ["punctuation", "="], ["value", ["baz28"]], + ["key", "bar29"], ["punctuation", "="], ["value", ["baz29 qux29"]], + ["key", "bar30"], ["punctuation", "="], ["value", ["baz30=qux30"]] +] + +---------------------------------------------------- + +Checks for key-value pairs. diff --git a/tests/languages/ini/selector_feature.test b/tests/languages/ini/punctuation_feature.test similarity index 51% rename from tests/languages/ini/selector_feature.test rename to tests/languages/ini/punctuation_feature.test index 3158a665da..c72a16d0a1 100644 --- a/tests/languages/ini/selector_feature.test +++ b/tests/languages/ini/punctuation_feature.test @@ -1,13 +1,11 @@ -[owner] -[foobar] - ----------------------------------------------------- - -[ - ["selector", "[owner]"], - ["selector", "[foobar]"] -] - ----------------------------------------------------- - -Checks for section titles. \ No newline at end of file += + +---------------------------------------------------- + +[ + ["punctuation", "="] +] + +---------------------------------------------------- + +Checks for punctuation marks.