Skip to content

Commit

Permalink
Tests: lookbehind test for patterns (#1890)
Browse files Browse the repository at this point in the history
This adds a test which whether `lookbehind` (if set to `true`) is necessary for a given pattern.
  • Loading branch information
RunDevelopment authored Jun 2, 2019
1 parent a816455 commit 3ba786c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 22 deletions.
6 changes: 1 addition & 5 deletions components/prism-elixir.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
Prism.languages.elixir = {
'comment': {
pattern: /#.*/m,
lookbehind: true
},
'comment': /#.*/m,
// ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r<foo>
'regex': {
pattern: /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,
Expand Down Expand Up @@ -90,4 +87,3 @@ Prism.languages.elixir.string.forEach(function(o) {
}
};
});

2 changes: 1 addition & 1 deletion components/prism-elixir.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 6 additions & 9 deletions components/prism-tt2.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
(function(Prism) {

Prism.languages.tt2 = Prism.languages.extend('clike', {
comment: {
pattern: /#.*|\[%#[\s\S]*?%\]/,
lookbehind: true
},
keyword: /\b(?:BLOCK|CALL|CASE|CATCH|CLEAR|DEBUG|DEFAULT|ELSE|ELSIF|END|FILTER|FINAL|FOREACH|GET|IF|IN|INCLUDE|INSERT|LAST|MACRO|META|NEXT|PERL|PROCESS|RAWPERL|RETURN|SET|STOP|TAGS|THROW|TRY|SWITCH|UNLESS|USE|WHILE|WRAPPER)\b/,
punctuation: /[[\]{},()]/
'comment': /#.*|\[%#[\s\S]*?%\]/,
'keyword': /\b(?:BLOCK|CALL|CASE|CATCH|CLEAR|DEBUG|DEFAULT|ELSE|ELSIF|END|FILTER|FINAL|FOREACH|GET|IF|IN|INCLUDE|INSERT|LAST|MACRO|META|NEXT|PERL|PROCESS|RAWPERL|RETURN|SET|STOP|TAGS|THROW|TRY|SWITCH|UNLESS|USE|WHILE|WRAPPER)\b/,
'punctuation': /[[\]{},()]/
});

Prism.languages.insertBefore('tt2', 'number', {
operator: /=[>=]?|!=?|<=?|>=?|&&|\|\|?|\b(?:and|or|not)\b/,
variable: {
'operator': /=[>=]?|!=?|<=?|>=?|&&|\|\|?|\b(?:and|or|not)\b/,
'variable': {
pattern: /[a-z]\w*(?:\s*\.\s*(?:\d+|\$?[a-z]\w*))*/i
}
});
Expand All @@ -34,7 +31,7 @@
greedy: true,
alias: 'string',
inside: {
variable: {
'variable': {
pattern: /\$(?:[a-z]\w*(?:\.(?:\d+|\$?[a-z]\w*))*)/i
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/prism-tt2.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 45 additions & 6 deletions tests/regex-tests.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"use strict";

const { assert } = require("chai");
const { assert } = require('chai');
const PrismLoader = require('./helper/prism-loader');
const { languages } = require('../components');


for (const lang in languages) {
if (lang === 'meta') {
continue;
Expand All @@ -13,19 +14,57 @@ for (const lang in languages) {

const Prism = PrismLoader.createInstance(lang);

it('- should not match the empty string', function () {
let lastToken = '<unknown>';
/**
* Invokes the given function on every pattern in `Prism.languages`.
*
* @param {(values: { pattern: RegExp, tokenName: string, name: string, parent: any }) => void} callback
*/
function forEachPattern(callback) {
/** @type {Map<string, string>} */
const nameMap = new Map();

Prism.languages.DFS(Prism.languages, function (name, value) {
if (typeof this === 'object' && !Array.isArray(this) && name !== 'pattern') {
lastToken = name;
let path = nameMap.get(this) || '<languages>';
if (/^\d+$/.test(name)) {
path += `[${name}]`;
} else if (/^[a-z]\w*$/i.test(name)) {
path += `.${name}`;
} else {
path += `[${JSON.stringify(name)}]`;
}
if (Array.isArray(value) || Prism.util.type(value) === 'Object') {
nameMap.set(value, path);
}

if (Prism.util.type(value) === 'RegExp') {
assert.notMatch('', value, `Token '${lastToken}': ${value} should not match the empty string.`);
callback({
pattern: value,
tokenName: path,
name,
parent: this,
});
}
});
}


it('- should not match the empty string', function () {
forEachPattern(({ pattern, tokenName }) => {
// test for empty string
assert.notMatch('', pattern, `Token ${tokenName}: ${pattern} should not match the empty string.`);
});
});

it('- should have a capturing group if lookbehind is set to true', function () {
forEachPattern(({ pattern, tokenName, name, parent }) => {
if (name === 'pattern' && parent.lookbehind) {
const simplifiedSource = pattern.source.replace(/\\\D/g, '_').replace(/\[[^\]]*\]/g, '_');

if (!/\((?!\?)/.test(simplifiedSource)) {
assert.fail(`Token ${tokenName}: The pattern is set to 'lookbehind: true' but does not have a capturing group.`);
}
}
});
});
});
}

0 comments on commit 3ba786c

Please sign in to comment.