From 346a95b0fe65b847daad1af7f23f3a738fe5e5dd Mon Sep 17 00:00:00 2001 From: "Ludger A. Rinsche" Date: Tue, 13 Oct 2020 20:00:40 +0200 Subject: [PATCH 1/2] initial introduction of rich and richer chars Currently the system is VERY restricted about which classnames are allowed. This will allow a lot of characters and allows to name the classname in quotes. --- src/plantuml.js | 145 +++++++++++++++++++++--------- src/plantuml.pegjs | 7 +- tests/complex/classnames.coffee | 17 ++++ tests/complex/classnames.plantuml | 17 ++++ 4 files changed, 143 insertions(+), 43 deletions(-) create mode 100644 tests/complex/classnames.coffee create mode 100644 tests/complex/classnames.plantuml diff --git a/src/plantuml.js b/src/plantuml.js index 362ce29..c93cebb 100644 --- a/src/plantuml.js +++ b/src/plantuml.js @@ -179,16 +179,20 @@ module.exports = (function() { peg$c140 = /^[^ ,\n\r\t(){}]/, peg$c141 = { type: "class", value: "[^ ,\\n\\r\\t(){}]", description: "[^ ,\\n\\r\\t(){}]" }, peg$c142 = function(items) { return items.join("") }, - peg$c143 = /^[A-Za-z_]/, - peg$c144 = { type: "class", value: "[A-Za-z_]", description: "[A-Za-z_]" }, - peg$c145 = /^[A-Za-z0-9.]/, - peg$c146 = { type: "class", value: "[A-Za-z0-9.]", description: "[A-Za-z0-9.]" }, - peg$c147 = function(objectname) { return [objectname[0], objectname[1].join("")].join("") }, + peg$c143 = function(item) { return item.join("") }, + peg$c144 = "\"", + peg$c145 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c146 = /^[A-Za-z_]/, + peg$c147 = { type: "class", value: "[A-Za-z_]", description: "[A-Za-z_]" }, peg$c148 = /^[A-Za-z0-9_]/, peg$c149 = { type: "class", value: "[A-Za-z0-9_]", description: "[A-Za-z0-9_]" }, peg$c150 = function(items) { return [items[0], items[1].join("")].join("") }, peg$c151 = /^[+]/, peg$c152 = { type: "class", value: "[+]", description: "[+]" }, + peg$c153 = /^[A-Za-z0-9_:;~#!\xA7$()[\]+\-*\\\/|,]/, + peg$c154 = { type: "class", value: "[A-Za-z0-9_:;~#!\xA7$()\\[\\]\\+\\-\\*\\\\/|,]", description: "[A-Za-z0-9_:;~#!\xA7$()\\[\\]\\+\\-\\*\\\\/|,]" }, + peg$c155 = /^[A-Za-z0-9_:;~#!\xA7$()[\]+\-*\\\/|,{} ]/, + peg$c156 = { type: "class", value: "[A-Za-z0-9_:;~#!\xA7$()\\[\\]\\+\\-\\*\\\\/|,{} ]", description: "[A-Za-z0-9_:;~#!\xA7$()\\[\\]\\+\\-\\*\\\\/|,{} ]" }, peg$currPos = 0, peg$savedPos = 0, @@ -3472,52 +3476,51 @@ module.exports = (function() { } function peg$parseobjectname() { - var s0, s1, s2, s3, s4; + var s0, s1, s2, s3; s0 = peg$currPos; - s1 = peg$currPos; - if (peg$c143.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c144); } + s1 = peg$parserichchars(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c143(s1); } - if (s2 !== peg$FAILED) { - s3 = []; - if (peg$c145.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c144; peg$currPos++; } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c146); } + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c145); } } - while (s4 !== peg$FAILED) { - s3.push(s4); - if (peg$c145.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; + if (s1 !== peg$FAILED) { + s2 = peg$parsericherchars(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c144; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c145); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c143(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c146); } + peg$currPos = s0; + s0 = peg$FAILED; } - } - if (s3 !== peg$FAILED) { - s2 = [s2, s3]; - s1 = s2; } else { - peg$currPos = s1; - s1 = peg$FAILED; + peg$currPos = s0; + s0 = peg$FAILED; } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c147(s1); } - s0 = s1; return s0; } @@ -3527,12 +3530,12 @@ module.exports = (function() { s0 = peg$currPos; s1 = peg$currPos; - if (peg$c143.test(input.charAt(peg$currPos))) { + if (peg$c146.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c144); } + if (peg$silentFails === 0) { peg$fail(peg$c147); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3629,6 +3632,64 @@ module.exports = (function() { return s0; } + function peg$parserichchars() { + var s0, s1; + + s0 = []; + if (peg$c153.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c154); } + } + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + if (peg$c153.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c154); } + } + } + } else { + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsericherchars() { + var s0, s1; + + s0 = []; + if (peg$c155.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c156); } + } + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + if (peg$c155.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c156); } + } + } + } else { + s0 = peg$FAILED; + } + + return s0; + } + peg$result = peg$startRuleFunction(); if (peg$result !== peg$FAILED && peg$currPos === input.length) { diff --git a/src/plantuml.pegjs b/src/plantuml.pegjs index 5a887fa..2d8a905 100644 --- a/src/plantuml.pegjs +++ b/src/plantuml.pegjs @@ -111,7 +111,8 @@ methodparameter returntype = items:[^ ,\n\r\t(){}]+ { return items.join("") } objectname - = objectname:([A-Za-z_][A-Za-z0-9.]*) { return [objectname[0], objectname[1].join("")].join("") } + = item:(richchars) { return item.join("") } + / "\"" item:(richerchars) "\"" { return item.join("") } membername = items:([A-Za-z_][A-Za-z0-9_]*) { return [items[0], items[1].join("")].join("") } accessortype @@ -124,3 +125,7 @@ privateaccessor = [-] protectedaccessor = [#] +richchars + = [A-Za-z0-9_:;~#!§$()\[\]\+\-\*\\/|,]+ +richerchars + = [A-Za-z0-9_:;~#!§$()\[\]\+\-\*\\/|,{} ]+ \ No newline at end of file diff --git a/tests/complex/classnames.coffee b/tests/complex/classnames.coffee new file mode 100644 index 0000000..943a19e --- /dev/null +++ b/tests/complex/classnames.coffee @@ -0,0 +1,17 @@ +class someclass + + + +class §$noQuotes|_:;~#!§$()[]+-*\/,| + + + +class inQuotes + + + +class AZaz09 |_:;~#!§$()[]+-*\/,{}| + + + + diff --git a/tests/complex/classnames.plantuml b/tests/complex/classnames.plantuml new file mode 100644 index 0000000..586105f --- /dev/null +++ b/tests/complex/classnames.plantuml @@ -0,0 +1,17 @@ +@startuml +' node node_modules/pegjs/bin/pegjs src/plantuml.pegjs src/plantuml.js +' node plantcode -l coffeescript tests/complex/classnames.plantuml > tests/complex/classnames.coffee + +class someclass { +} + +class §$noQuotes|_:;~#!§$()[]+-*\/,| { +} + +class "inQuotes" { +} + +class "AZaz09 |_:;~#!§$()[]+-*\/,{}|" { +} + +@enduml \ No newline at end of file From 8b8c4bde51482342f4a1d8785d2754a9bebddc4c Mon Sep 17 00:00:00 2001 From: "Ludger A. Rinsche" Date: Tue, 13 Oct 2020 21:10:10 +0200 Subject: [PATCH 2/2] added classtypes I am not sure what the correct UML name is for these additional class information, but PlantUML supports them and now the plantuml-code-generator can handle them as well. I also edited the coffeescript template to "make use" of the new information. --- plantcode | 1 + src/Class.js | 7 ++++++- src/plantcode.js | 1 + src/plantuml.pegjs | 9 +++++---- templates/coffeescript.hbs | 1 + tests/complex/classnames.coffee | 14 ++++++++++++++ tests/complex/classnames.plantuml | 8 ++++++-- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/plantcode b/plantcode index ac43663..edb185a 100755 --- a/plantcode +++ b/plantcode @@ -179,6 +179,7 @@ function processTemplateFile(config, templateData, dictionary) { "getKeyword": true, "getMethods": true, "getName": true, + "getType": true, "getParameters": true, "getReturnType": true, "hasFields": true, diff --git a/src/Class.js b/src/Class.js index 571de34..ba04188 100644 --- a/src/Class.js +++ b/src/Class.js @@ -4,10 +4,11 @@ module.exports = (function () { var Field = require("./Field"); var Method = require("./Method"); - var Class = function (className, fileLines) { + var Class = function (className, fileLines, classType) { this.cExtends = null; this.fileLines = fileLines || []; this.className = className; + this.classType = classType || ""; this.nNamespace = null; } @@ -39,6 +40,10 @@ module.exports = (function () { return this.className; } + Class.prototype.getType = function () { + return this.classType; + } + Class.prototype.hasMethods = function () { for (var i = 0, length = this.fileLines.length; i < length; i++) { if (this.fileLines[i] instanceof Method) { diff --git a/src/plantcode.js b/src/plantcode.js index 376e12d..ace2616 100644 --- a/src/plantcode.js +++ b/src/plantcode.js @@ -73,6 +73,7 @@ function processTemplateFile(config, templateData, dictionary) { "getKeyword": true, "getMethods": true, "getName": true, + "getType": true, "getParameters": true, "getReturnType": true, "hasFields": true, diff --git a/src/plantuml.pegjs b/src/plantuml.pegjs index 2d8a905..b2f0427 100644 --- a/src/plantuml.pegjs +++ b/src/plantuml.pegjs @@ -79,10 +79,9 @@ newline = [\r\n] / [\n] classdeclaration - = noise "class " noise classname:objectname noise startblock lines:umllines endblock { var Class = require("./Class"); return new Class(classname, lines) } - / noise "class " noise classname:objectname noise "<<" noise [^>]+ noise ">>" noise { var Class = require("./Class"); return new Class(classname) } - / noise "class " noise classname:objectname noise { var Class = require("./Class"); return new Class(classname) } - / noise "class " noise classname:objectname noise newline noise lines:umllines "end class" { var Class = require("./Class"); return new Class(classname, lines) } + = noise "class " noise classname:objectname noise classtype:objecttype? noise startblock lines:umllines endblock { var Class = require("./Class"); return new Class(classname, lines, classtype) } + / noise "class " noise classname:objectname noise classtype:objecttype? noise { var Class = require("./Class"); return new Class(classname, null, classtype) } + / noise "class " noise classname:objectname noise classtype:objecttype? noise newline noise lines:umllines "end class" { var Class = require("./Class"); return new Class(classname, lines, classtype) } interfacedeclaration = noise "interface " noise interfacename:objectname noise startblock lines:umllines endblock { var Interface = require("./Interface"); return new Interface(interfacename, lines) } / noise "interface " noise interfacename:objectname noise "<<" noise [^>]+ noise ">>" noise { var Interface = require("./Interface"); return new Interface(interfacename) } @@ -113,6 +112,8 @@ returntype objectname = item:(richchars) { return item.join("") } / "\"" item:(richerchars) "\"" { return item.join("") } +objecttype + = "<<" noise item:(richerchars) noise ">>" { return item.join("") } membername = items:([A-Za-z_][A-Za-z0-9_]*) { return [items[0], items[1].join("")].join("") } accessortype diff --git a/templates/coffeescript.hbs b/templates/coffeescript.hbs index 66953cd..85d666a 100644 --- a/templates/coffeescript.hbs +++ b/templates/coffeescript.hbs @@ -1,4 +1,5 @@ {{#if_ne getKeyword "interface"}}class {{getFullName}}{{#if getExtends}} extends {{#with getExtends}}{{getFullName}}{{/with}}{{/if}} +{{#if getType}}# was typed as <<{{getType}}>>{{/if}} {{#each getFields}} {{this.getName}}: undefined {{/each}} diff --git a/tests/complex/classnames.coffee b/tests/complex/classnames.coffee index 943a19e..a1f0a28 100644 --- a/tests/complex/classnames.coffee +++ b/tests/complex/classnames.coffee @@ -2,16 +2,30 @@ class someclass + class §$noQuotes|_:;~#!§$()[]+-*\/,| + class inQuotes + class AZaz09 |_:;~#!§$()[]+-*\/,{}| +class withDescr1 +# was typed as <> + + + +class withDescr2 +# was typed as <> + + + + diff --git a/tests/complex/classnames.plantuml b/tests/complex/classnames.plantuml index 586105f..7b9386b 100644 --- a/tests/complex/classnames.plantuml +++ b/tests/complex/classnames.plantuml @@ -2,8 +2,7 @@ ' node node_modules/pegjs/bin/pegjs src/plantuml.pegjs src/plantuml.js ' node plantcode -l coffeescript tests/complex/classnames.plantuml > tests/complex/classnames.coffee -class someclass { -} +class someclass class §$noQuotes|_:;~#!§$()[]+-*\/,| { } @@ -14,4 +13,9 @@ class "inQuotes" { class "AZaz09 |_:;~#!§$()[]+-*\/,{}|" { } +class "withDescr1" <> + +class "withDescr2" <> { +} + @enduml \ No newline at end of file