diff --git a/VHDLFormatter.html b/VHDLFormatter.html index b29747f..b3eb335 100644 --- a/VHDLFormatter.html +++ b/VHDLFormatter.html @@ -129,7 +129,7 @@ , , + PORT or PORT MAP,
diff --git a/VHDLFormatter.js b/VHDLFormatter.js index d91b094..8189e8b 100644 --- a/VHDLFormatter.js +++ b/VHDLFormatter.js @@ -2,6 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); let isTesting = false; const ILCommentPrefix = "@@comments"; +const ILQuotesPrefix = "@@quotes"; class NewLineSettings { constructor() { this.newLineAfter = []; @@ -226,7 +227,7 @@ function SetNewLinesAfterSymbols(text, newLineSettings) { class BeautifierSettings { constructor(removeComments, removeReport, checkAlias, signAlign, signAlignAll, keywordCase, indentation, newLineSettings) { this.RemoveComments = removeComments; - this.RemoveReport = removeReport; + this.RemoveAsserts = removeReport; this.CheckAlias = checkAlias; this.SignAlign = signAlign; this.SignAlignAll = signAlignAll; @@ -251,58 +252,39 @@ function beautify(input, settings) { if (settings.RemoveComments) { input = input.replace(/@@comments[0-9]+/g, ''); } - var quotes = [], quotesIndex = 0; + input = ReplaceKeyWords(input, KeyWords); + input = ReplaceKeyWords(input, TypeNames); + input = input.replace(/(PORT|PROCESS|GENERIC)[\s]*\(/g, '$1 ('); + input = SetNewLinesAfterSymbols(input, settings.NewLineSettings); + input = beautify2(input, settings); + for (var k = 0; k < commentsIndex; k++) { + input = input.replace(ILCommentPrefix + k, comments[k]); + } + input = input.replace(/@@semicolon/g, ";"); + input = input.replace(/@@[a-z]+/g, ""); + return input; +} +exports.beautify = beautify; +function beautify2(input, settings) { + let arr = input.split("\r\n"); + let quotes = EscapeQuotes(arr); + if (settings.RemoveAsserts) { + RemoveAsserts(arr); //RemoveAsserts must be after EscapeQuotes + } var singleline = [], singlelineIndex = 0; var align = [], align_max = [], align_i1 = 0, align_i = 0; var str = "", str1 = ""; var p = 0; var n = 0, j = 0; var tab_n = 0, str_len = 0, port_s = ""; - var back_tab = false, forward_tab = false, need_semi = false, semi_pos = 0, begin_b = true, port_b = false; - input = ReplaceKeyWords(input, KeyWords); - input = ReplaceKeyWords(input, TypeNames); - input = input.replace(/(PORT|PROCESS|GENERIC)[\s]*\(/g, '$1 ('); - input = SetNewLinesAfterSymbols(input, settings.NewLineSettings); - arr = input.split("\r\n"); - var l = arr.length; + var back_tab = false, forward_tab = false, semi_pos = 0, begin_b = true, port_b = false; var before_begin = true; + var l = arr.length; + ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); for (i = 0; i < l; i++) { - let k4 = arr[i].match(/"([^"]+)"/g); - if (k4 != null) { - var u = k4.length; - for (var j = 0; j < u; j++) { - arr[i] = arr[i].replace(k4[j], "@@quotes" + quotesIndex); - quotes[quotesIndex++] = k4[j]; - } - } if (arr[i].indexOf("BEGIN") >= 0) { before_begin = false; } - if (settings.RemoveReport) { - n = arr[i].indexOf("REPORT "); - p = arr[i].indexOf(";"); - if (need_semi) { - arr[i] = ''; - if (p >= 0) { - need_semi = false; - } - } - if (n >= 0) { - arr[i] = ''; - if (p < 0) { - need_semi = true; - } - } - else if (n < 0) { - n = arr[i].indexOf("ASSERT "); - if (n >= 0) { - arr[i] = ''; - if (p < 0) { - need_semi = true; - } - } - } - } if (arr[i].match(/FUNCTION|PROCEDURE/) != null) { arr[i] = arr[i].replace(/;/g, '@@semicolon'); } @@ -332,12 +314,6 @@ function beautify(input, settings) { arr[i] = arr[i].replace(/(PORT|GENERIC|PROCEDURE)([a-z0-9A-Z_ ]+)\(([a-zA-Z0-9_\(\) ]+)/, '$1$2(\r\n$3'); } } - /*if (!new_line) { - if (arr[i].regexIndexOf(/(;|THEN)[ a-z0-9]+[a-z0-9]+/) >= 0) { - singleline[singlelineIndex] = arr[i]; - arr[i] = "@@singleline" + singlelineIndex++; - } - }*/ } input = arr.join("\r\n"); input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); @@ -354,9 +330,6 @@ function beautify(input, settings) { input = input.replace(/\r\n\r\n\r\n/g, '\r\n'); input = input.replace(/[\r\n\s]+$/g, ''); input = input.replace(/[ \t]+\)/g, ')'); - //if (remove_lines) { - // input = input.replace(/(\r\n)*[ \t]*\r\n/g, '\r\n'); - //} var matches = input.match(/'([a-zA-Z]+)\s/g); if (matches != null) { for (var k2 = 0; k2 < matches.length; k2++) { @@ -488,17 +461,19 @@ function beautify(input, settings) { back_tab = true; begin_b = true; } - if (port_b && str.indexOf("@@") < 0 && arr[i + 1].indexOf("@@") < 0) { - if (signAlignPos == ":") { - if (str.indexOf(';') < 0) { - arr[i] += arr[i + 1]; - arr[i + 1] = '@@removeline'; + if (port_b && str.indexOf("@@") < 0) { + if (i + 1 <= arr.length - 1 && arr[i + 1].indexOf("@@") < 0) { + if (signAlignPos == ":") { + if (str.indexOf(';') < 0) { + arr[i] += arr[i + 1]; + arr[i + 1] = '@@removeline'; + } } - } - else if (signAlignPos == "=>") { - if (str.indexOf(',') < 0) { - arr[i] += arr[i + 1]; - arr[i + 1] = '@@removeline'; + else if (signAlignPos == "=>") { + if (str.indexOf(',') < 0) { + arr[i] += arr[i + 1]; + arr[i + 1] = '@@removeline'; + } } } } @@ -512,9 +487,11 @@ function beautify(input, settings) { signAlignPos = "=>"; } else { - t = arr[i + 1].indexOf("=>"); - if (t >= 0) { - signAlignPos = "=>"; + if (i + 1 < arr.length) { + t = arr[i + 1].indexOf("=>"); + if (t >= 0) { + signAlignPos = "=>"; + } } } } @@ -644,11 +621,16 @@ function beautify(input, settings) { console.log(tab_n, arr[i], indent_start); } arr[i] = (Array(tab_n).join(settings.Indentation)) + arr[i]; //indent - /*if (new_line_after_port) { + if (settings.NewLineSettings.newLineAfter.indexOf("port")) { + if (str.indexOf('@@singleend') < 0) { + arr[i] = arr[i].replace(/(PORT)([ \r\n\w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(settings.Indentation)) + "("); + } + } + if (settings.NewLineSettings.newLineAfter.indexOf("generic")) { if (str.indexOf('@@singleend') < 0) { - arr[i] = arr[i].replace(/(PORT|GENERIC)([ \w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(indentation)) + "("); + arr[i] = arr[i].replace(/(GENERIC)([ \r\n\w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(settings.Indentation)) + "("); } - }*/ + } } if (back_tab) { tab_n++; @@ -678,7 +660,7 @@ function beautify(input, settings) { else if (first_word == "WHEN" && i + 1 < arr.length && arr[i + 1].indexOf("WHEN") < 0) { tab_n = indent_start_last + 1; } - else if (str.indexOf("=>") < 0 && ((str.indexOf("@@quotes") >= 0 && str.indexOf("= @@quotes") < 0 && str.indexOf("IF") < 0) || (str.indexOf("<=") > 0 && str.indexOf("IF") < 0 && str.indexOf("THEN") < 0))) { + else if (str.indexOf("=>") < 0 && ((str.indexOf(ILQuotesPrefix) >= 0 && str.indexOf("= " + ILQuotesPrefix) < 0 && str.indexOf("IF") < 0) || (str.indexOf("<=") > 0 && str.indexOf("IF") < 0 && str.indexOf("THEN") < 0))) { tab_n++; indent_start.push(tab_n); semi_b = true; @@ -765,20 +747,65 @@ function beautify(input, settings) { input = input.replace("@@align" + k, Array((align_max[k] - align[k] + 2)).join(" ")); } } - for (var k = 0; k < quotesIndex; k++) { - input = input.replace("@@quotes" + k, quotes[k]); + for (var k = 0; k < quotes.length; k++) { + input = input.replace(ILQuotesPrefix + k, quotes[k]); } - for (var k = 0; k < singlelineIndex; k++) { - input = input.replace("@@singleline" + k, singleline[k]); + input = input.replace(/@@singleline[ \r\n]*/, " "); + return input; +} +function ApplyNoNewLineAfter(arr, noNewLineAfter) { + if (noNewLineAfter == null) { + return; } - for (var k = 0; k < commentsIndex; k++) { - input = input.replace(ILCommentPrefix + k, comments[k]); + for (let i = 0; i < arr.length; i++) { + noNewLineAfter.forEach(n => { + let regex = new RegExp("(" + n.toUpperCase + ")[ a-z0-9]+[a-z0-9]+"); + if (arr[i].regexIndexOf(regex) >= 0) { + arr[i] += "@@singleline"; + } + }); } - input = input.replace(/@@semicolon/g, ";"); - input = input.replace(/@@[a-z]+/g, ""); - return input; } -exports.beautify = beautify; +exports.ApplyNoNewLineAfter = ApplyNoNewLineAfter; +function RemoveAsserts(arr) { + let need_semi = false; + let inAssert = false; + let n = 0; + for (let i = 0; i < arr.length; i++) { + let has_semi = arr[i].indexOf(";") >= 0; + if (need_semi) { + arr[i] = ''; + } + n = arr[i].indexOf("ASSERT "); + if (n >= 0) { + inAssert = true; + arr[i] = ''; + } + if (!has_semi) { + if (inAssert) { + need_semi = true; + } + } + else { + need_semi = false; + } + } +} +exports.RemoveAsserts = RemoveAsserts; +function EscapeQuotes(arr) { + let quotes = []; + let quotesIndex = 0; + for (let i = 0; i < arr.length; i++) { + let quote = arr[i].match(/"([^"]+)"/g); + if (quote != null) { + for (var j = 0; j < quote.length; j++) { + arr[i] = arr[i].replace(quote[j], ILQuotesPrefix + quotesIndex); + quotes[quotesIndex++] = quote[j]; + } + } + } + return quotes; +} function RemoveExtraNewLines(input) { input = input.replace(/(?:\r\n|\r|\n)/g, '\r\n'); input = input.replace(/ \r\n/g, '\r\n'); diff --git a/VHDLFormatter.ts b/VHDLFormatter.ts index 891f669..2654c47 100644 --- a/VHDLFormatter.ts +++ b/VHDLFormatter.ts @@ -1,5 +1,6 @@ let isTesting = false; const ILCommentPrefix = "@@comments"; +const ILQuotesPrefix = "@@quotes"; export class NewLineSettings { newLineAfter: Array; @@ -246,7 +247,7 @@ function SetNewLinesAfterSymbols(text: string, newLineSettings: NewLineSettings) export class BeautifierSettings { RemoveComments: boolean; - RemoveReport: boolean; + RemoveAsserts: boolean; CheckAlias: boolean; SignAlign: boolean; SignAlignAll: boolean; @@ -257,7 +258,7 @@ export class BeautifierSettings { signAlign: boolean, signAlignAll: boolean, keywordCase: string, indentation: string, newLineSettings: NewLineSettings) { this.RemoveComments = removeComments; - this.RemoveReport = removeReport; + this.RemoveAsserts = removeReport; this.CheckAlias = checkAlias; this.SignAlign = signAlign; this.SignAlignAll = signAlignAll; @@ -304,8 +305,12 @@ export function beautify(input: string, settings: BeautifierSettings) { } function beautify2(input, settings: BeautifierSettings): string { - var quotes = [], - quotesIndex = 0; + let arr = input.split("\r\n"); + let quotes = EscapeQuotes(arr); + if (settings.RemoveAsserts) { + RemoveAsserts(arr);//RemoveAsserts must be after EscapeQuotes + } + var singleline = [], singlelineIndex = 0; var align = [], @@ -322,53 +327,17 @@ function beautify2(input, settings: BeautifierSettings): string { port_s = ""; var back_tab = false, forward_tab = false, - need_semi = false, semi_pos = 0, begin_b = true, port_b = false; - - let arr = input.split("\r\n"); - var l = arr.length; var before_begin = true; + var l = arr.length; + ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); for (i = 0; i < l; i++) { - let k4 = arr[i].match(/"([^"]+)"/g); - if (k4 != null) { - var u = k4.length; - for (var j = 0; j < u; j++) { - arr[i] = arr[i].replace(k4[j], "@@quotes" + quotesIndex); - quotes[quotesIndex++] = k4[j]; - } - } - if (arr[i].indexOf("BEGIN") >= 0) { before_begin = false; } - if (settings.RemoveReport) { - n = arr[i].indexOf("REPORT "); - p = arr[i].indexOf(";"); - if (need_semi) { - arr[i] = ''; - if (p >= 0) { - need_semi = false; - } - } - if (n >= 0) { - arr[i] = ''; - if (p < 0) { - need_semi = true; - } - } else if (n < 0) { - n = arr[i].indexOf("ASSERT "); - if (n >= 0) { - arr[i] = ''; - if (p < 0) { - need_semi = true; - } - } - } - } - if (arr[i].match(/FUNCTION|PROCEDURE/) != null) { arr[i] = arr[i].replace(/;/g, '@@semicolon'); } @@ -396,12 +365,7 @@ function beautify2(input, settings: BeautifierSettings): string { arr[i] = arr[i].replace(/(PORT|GENERIC|PROCEDURE)([a-z0-9A-Z_ ]+)\(([a-zA-Z0-9_\(\) ]+)/, '$1$2(\r\n$3'); } } - /*if (!new_line) { - if (arr[i].regexIndexOf(/(;|THEN)[ a-z0-9]+[a-z0-9]+/) >= 0) { - singleline[singlelineIndex] = arr[i]; - arr[i] = "@@singleline" + singlelineIndex++; - } - }*/ + } input = arr.join("\r\n"); input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); @@ -418,9 +382,7 @@ function beautify2(input, settings: BeautifierSettings): string { input = input.replace(/\r\n\r\n\r\n/g, '\r\n'); input = input.replace(/[\r\n\s]+$/g, ''); input = input.replace(/[ \t]+\)/g, ')'); - //if (remove_lines) { - // input = input.replace(/(\r\n)*[ \t]*\r\n/g, '\r\n'); - //} + var matches = input.match(/'([a-zA-Z]+)\s/g); if (matches != null) { for (var k2 = 0; k2 < matches.length; k2++) { @@ -563,16 +525,18 @@ function beautify2(input, settings: BeautifierSettings): string { back_tab = true; begin_b = true; } - if (port_b && str.indexOf("@@") < 0 && arr[i + 1].indexOf("@@") < 0) { - if (signAlignPos == ":") { - if (str.indexOf(';') < 0) { - arr[i] += arr[i + 1]; - arr[i + 1] = '@@removeline'; - } - } else if (signAlignPos == "=>") { - if (str.indexOf(',') < 0) { - arr[i] += arr[i + 1]; - arr[i + 1] = '@@removeline'; + if (port_b && str.indexOf("@@") < 0) { + if (i + 1 <= arr.length - 1 && arr[i + 1].indexOf("@@") < 0) { + if (signAlignPos == ":") { + if (str.indexOf(';') < 0) { + arr[i] += arr[i + 1]; + arr[i + 1] = '@@removeline'; + } + } else if (signAlignPos == "=>") { + if (str.indexOf(',') < 0) { + arr[i] += arr[i + 1]; + arr[i + 1] = '@@removeline'; + } } } } @@ -585,9 +549,11 @@ function beautify2(input, settings: BeautifierSettings): string { if (t >= 0) { signAlignPos = "=>"; } else { - t = arr[i + 1].indexOf("=>"); - if (t >= 0) { - signAlignPos = "=>"; + if (i + 1 < arr.length) { + t = arr[i + 1].indexOf("=>"); + if (t >= 0) { + signAlignPos = "=>"; + } } } } else { @@ -706,11 +672,16 @@ function beautify2(input, settings: BeautifierSettings): string { console.log(tab_n, arr[i], indent_start); } arr[i] = (Array(tab_n).join(settings.Indentation)) + arr[i]; //indent - /*if (new_line_after_port) { + if (settings.NewLineSettings.newLineAfter.indexOf("port")) { + if (str.indexOf('@@singleend') < 0) { + arr[i] = arr[i].replace(/(PORT)([ \r\n\w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(settings.Indentation)) + "("); + } + } + if (settings.NewLineSettings.newLineAfter.indexOf("generic")) { if (str.indexOf('@@singleend') < 0) { - arr[i] = arr[i].replace(/(PORT|GENERIC)([ \w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(indentation)) + "("); + arr[i] = arr[i].replace(/(GENERIC)([ \r\n\w]*)\(/, "$1$2\r\n" + (Array(tab_n).join(settings.Indentation)) + "("); } - }*/ + } } if (back_tab) { tab_n++; @@ -737,7 +708,7 @@ function beautify2(input, settings: BeautifierSettings): string { white_space = (Array(str.indexOf("= ") + 3).join(" ")); } else if (first_word == "WHEN" && i + 1 < arr.length && arr[i + 1].indexOf("WHEN") < 0) { tab_n = indent_start_last + 1; - } else if (str.indexOf("=>") < 0 && ((str.indexOf("@@quotes") >= 0 && str.indexOf("= @@quotes") < 0 && str.indexOf("IF") < 0) || (str.indexOf("<=") > 0 && str.indexOf("IF") < 0 && str.indexOf("THEN") < 0))) { + } else if (str.indexOf("=>") < 0 && ((str.indexOf(ILQuotesPrefix) >= 0 && str.indexOf("= " + ILQuotesPrefix) < 0 && str.indexOf("IF") < 0) || (str.indexOf("<=") > 0 && str.indexOf("IF") < 0 && str.indexOf("THEN") < 0))) { tab_n++; indent_start.push(tab_n); semi_b = true; @@ -824,16 +795,67 @@ function beautify2(input, settings: BeautifierSettings): string { } } - for (var k = 0; k < quotesIndex; k++) { - input = input.replace("@@quotes" + k, quotes[k]); + for (var k = 0; k < quotes.length; k++) { + input = input.replace(ILQuotesPrefix + k, quotes[k]); } - for (var k = 0; k < singlelineIndex; k++) { - input = input.replace("@@singleline" + k, singleline[k]); + input = input.replace(/@@singleline[ \r\n]*/, " "); + return input; +} + + +export function ApplyNoNewLineAfter(arr: Array, noNewLineAfter: Array) { + if (noNewLineAfter == null) { + return; + } + for (let i = 0; i < arr.length; i++) { + noNewLineAfter.forEach(n => { + let regex = new RegExp("(" + n.toUpperCase + ")[ a-z0-9]+[a-z0-9]+"); + if (arr[i].regexIndexOf(regex) >= 0) { + arr[i] += "@@singleline"; + } + }); } +} +export function RemoveAsserts(arr: Array) { + let need_semi: boolean = false; + let inAssert: boolean = false; + let n: number = 0; + for (let i = 0; i < arr.length; i++) { + let has_semi: boolean = arr[i].indexOf(";") >= 0; + if (need_semi) { + arr[i] = ''; + } + n = arr[i].indexOf("ASSERT "); + if (n >= 0) { + inAssert = true; + arr[i] = ''; + } + if (!has_semi) { + if (inAssert) { + need_semi = true; + } + } + else { + need_semi = false; + } + } +} - return input; +function EscapeQuotes(arr: Array): Array { + let quotes: Array = []; + let quotesIndex = 0; + for (let i = 0; i < arr.length; i++) { + let quote = arr[i].match(/"([^"]+)"/g); + if (quote != null) { + for (var j = 0; j < quote.length; j++) { + arr[i] = arr[i].replace(quote[j], ILQuotesPrefix + quotesIndex); + quotes[quotesIndex++] = quote[j]; + } + } + } + return quotes; } function RemoveExtraNewLines(input: any) { diff --git a/VHDLFormatterUnitTests.js b/VHDLFormatterUnitTests.js index 0c72eaf..ccd60c1 100644 --- a/VHDLFormatterUnitTests.js +++ b/VHDLFormatterUnitTests.js @@ -4,10 +4,34 @@ const VHDLFormatter_1 = require("./VHDLFormatter"); const VHDLFormatter_2 = require("./VHDLFormatter"); const VHDLFormatter_3 = require("./VHDLFormatter"); const VHDLFormatter_4 = require("./VHDLFormatter"); +const VHDLFormatter_5 = require("./VHDLFormatter"); +const VHDLFormatter_6 = require("./VHDLFormatter"); var showUnitTests = true; //window.location.href.indexOf("http") < 0; if (showUnitTests) { UnitTest(); UnitTestIndentDecode(); + UnitTestRemoveAsserts(); + UnitTestApplyNoNewLineAfter(); +} +function UnitTestApplyNoNewLineAfter() { + console.log("=== ApplyNoNewLineAfter ==="); + let input = ["a;", "b;"]; + let expected = ["a;@@singleline", "b;@@singleline"]; + let parameters = [";"]; + UnitTest4(VHDLFormatter_6.ApplyNoNewLineAfter, "one blankspace", parameters, input, expected); + input = ["a;", "b THEN", "c"]; + expected = ["a;@@singleline", "b THEN@@singleline", "c"]; + parameters = [";", "then"]; + UnitTest4(VHDLFormatter_6.ApplyNoNewLineAfter, "one blankspace", parameters, input, expected); +} +function UnitTestRemoveAsserts() { + console.log("=== RemoveAsserts ==="); + let input = ["ASSERT a;"]; + let expected = [""]; + UnitTest3(VHDLFormatter_5.RemoveAsserts, "one assert", input, expected); + input = ["ASSERT a", "b;", "c"]; + expected = ["", "", "c"]; + UnitTest3(VHDLFormatter_5.RemoveAsserts, "multiline assert", input, expected); } function UnitTestIndentDecode() { console.log("=== IndentDecode ==="); @@ -25,6 +49,25 @@ function assert(testName, expected, actual, message) { //console.log(testName + " pass"); } } +function assertArray(testName, expected, actual, message) { + var result = CompareArray(actual, expected); + if (result != true) { + console.log(testName + " failed: " + result); + } + else { + //console.log(testName + " pass"); + } +} +function UnitTest4(func, testName, parameters, inputs, expected) { + let actual = JSON.parse(JSON.stringify(inputs)); + func(actual, parameters); + assertArray(testName, expected, actual); +} +function UnitTest3(func, testName, inputs, expected) { + let actual = JSON.parse(JSON.stringify(inputs)); + func(actual); + assertArray(testName, expected, actual); +} function UnitTest2(func, testName, inputs, expected) { let actual = func(inputs); assert(testName, expected, actual); @@ -34,17 +77,33 @@ function deepCopy(objectToCopy) { } function UnitTest() { let new_line_after_symbols = new VHDLFormatter_3.NewLineSettings(); - new_line_after_symbols.newLineAfter = ["Then", ";"]; + new_line_after_symbols.newLineAfter = ["then", ";"]; + new_line_after_symbols.noNewLineAfter = ["port", "generic"]; let settings = new VHDLFormatter_4.BeautifierSettings(false, false, false, false, false, "uppercase", " ", new_line_after_symbols); let input = "architecture TB of TB_CPU is\r\n component CPU_IF\r\n port -- port list\r\n end component;\r\n signal CPU_DATA_VALID: std_ulogic;\r\n signal CLK, RESET: std_ulogic := '0';\r\n constant PERIOD : time := 10 ns;\r\n constant MAX_SIM: time := 50 * PERIOD;\r\n begin\r\n -- concurrent statements\r\n end TB;"; let expected = "ARCHITECTURE TB OF TB_CPU IS\r\n COMPONENT CPU_IF\r\n PORT -- port list\r\n END COMPONENT;\r\n SIGNAL CPU_DATA_VALID : std_ulogic;\r\n SIGNAL CLK, RESET : std_ulogic := '0';\r\n CONSTANT PERIOD : TIME := 10 ns;\r\n CONSTANT MAX_SIM : TIME := 50 * PERIOD;\r\nBEGIN\r\n -- concurrent statements\r\nEND TB;"; let actual = VHDLFormatter_1.beautify(input, settings); - console.log("General", actual == expected); + console.log("General", CompareString(actual, expected)); let newSettings = deepCopy(settings); newSettings.RemoveComments = true; expected = "ARCHITECTURE TB OF TB_CPU IS\r\n COMPONENT CPU_IF\r\n PORT \r\n END COMPONENT;\r\n SIGNAL CPU_DATA_VALID : std_ulogic;\r\n SIGNAL CLK, RESET : std_ulogic := '0';\r\n CONSTANT PERIOD : TIME := 10 ns;\r\n CONSTANT MAX_SIM : TIME := 50 * PERIOD;\r\nBEGIN\r\nEND TB;"; actual = VHDLFormatter_1.beautify(input, newSettings); - console.log("Remove comments", actual == expected); + console.log("Remove comments", CompareString(actual, expected)); + let new_line_after_symbols_2 = new VHDLFormatter_3.NewLineSettings(); + new_line_after_symbols_2.newLineAfter = []; + new_line_after_symbols_2.noNewLineAfter = ["then", ";", "generic", "port"]; + newSettings = deepCopy(settings); + newSettings.NewLineSettings = new_line_after_symbols_2; + expected = "a; b; c;"; + input = "a; \r\nb;\r\n c;"; + actual = VHDLFormatter_1.beautify(input, newSettings); + console.log("Remove line after ;", CompareString(actual, expected)); + newSettings = deepCopy(settings); + newSettings.RemoveAsserts = true; + input = "architecture arch of ent is\r\nbegin\r\n assert False report sdfjcsdfcsdj;\r\n assert False report sdfjcsdfcsdj severity note;\r\nend architecture;"; + expected = "ARCHITECTURE arch OF ent IS\r\nBEGIN\r\nEND ARCHITECTURE;"; + actual = VHDLFormatter_1.beautify(input, newSettings); + console.log("Remove asserts", CompareString(actual, expected)); input = "entity TB_DISPLAY is\r\n-- port declarations\r\nend TB_DISPLAY;\r\n\r\narchitecture TEST of TB_DISPLAY is\r\n-- signal declarations\r\nbegin\r\n-- component instance(s)\r\nend TEST;"; expected = "ENTITY TB_DISPLAY IS\r\n -- port declarations\r\nEND TB_DISPLAY;\r\n\r\nARCHITECTURE TEST OF TB_DISPLAY IS\r\n -- signal declarations\r\nBEGIN\r\n -- component instance(s)\r\nEND TEST;"; actual = VHDLFormatter_1.beautify(input, settings); @@ -85,12 +144,12 @@ function UnitTest() { console.log("Multiple PORT MAPs", CompareString(actual, expected)); input = "port (a : in std_logic;\r\n b : in std_logic;\r\n);"; expected = "PORT \r\n(\r\n a : IN std_logic;\r\n b : IN std_logic;\r\n);"; - let new_line_after_symbols_2 = new VHDLFormatter_3.NewLineSettings(); - new_line_after_symbols_2.newLineAfter = ["Then", ";", "generic", "port"]; + new_line_after_symbols_2 = new VHDLFormatter_3.NewLineSettings(); + new_line_after_symbols_2.newLineAfter = ["then", ";", "generic", "port"]; newSettings = deepCopy(settings); newSettings.NewLineSettings = new_line_after_symbols_2; actual = VHDLFormatter_1.beautify(input, newSettings); - console.log("New line aster PORT", CompareString(actual, expected)); + console.log("New line after PORT", CompareString(actual, expected)); input = "component a is\r\nport( Data : inout Std_Logic_Vector(7 downto 0););\r\nend component a;"; expected = "COMPONENT a IS\r\n PORT (Data : INOUT Std_Logic_Vector(7 DOWNTO 0););\r\nEND COMPONENT a;"; actual = VHDLFormatter_1.beautify(input, newSettings); @@ -119,7 +178,11 @@ function CompareString(actual, expected) { for (var i = 0; i < l; i++) { if (actual[i] != expected[i]) { var toEnd = Math.min(i + 50, l); - return '\ndifferent at ' + i.toString() + '\nactual: "\n' + actual.substring(i, toEnd) + '\nexpected: "\n' + expected.substring(i, toEnd) + '"' + "\nactual: \n" + actual; + return '\ndifferent at ' + i.toString() + + '\nactual: "\n' + actual.substring(i, toEnd) + + '\nexpected: "\n' + expected.substring(i, toEnd) + '"\n---' + + "\nactual (full): \n" + actual + "\n---" + + "\nexpected (full): \n" + expected + "\n====\n"; } } if (actual != expected) { @@ -127,4 +190,26 @@ function CompareString(actual, expected) { } return true; } +function CompareArray(actual, expected) { + var l = Math.min(actual.length, expected.length); + let result = ""; + for (var i = 0; i < l; i++) { + if (actual[i] != expected[i]) { + result += CompareString(actual[i], expected[i]) + "\n"; + } + } + if (actual.length > expected.length) { + result += "actual has more items"; + for (var i = expected.length; i < actual.length; i++) { + result += "actual[" + i + "] = " + actual[i]; + } + } + else if (actual.length < expected.length) { + result += "expected has more items"; + for (var i = actual.length; i < expected.length; i++) { + result += "expected[" + i + "] = " + expected[i]; + } + } + return true; +} //# sourceMappingURL=VHDLFormatterUnitTests.js.map \ No newline at end of file diff --git a/VHDLFormatterUnitTests.ts b/VHDLFormatterUnitTests.ts index 05cda21..55cd12b 100644 --- a/VHDLFormatterUnitTests.ts +++ b/VHDLFormatterUnitTests.ts @@ -2,17 +2,45 @@ import { beautify } from "./VHDLFormatter"; import { indentDecode } from "./VHDLFormatter"; import { NewLineSettings } from "./VHDLFormatter"; import { BeautifierSettings } from "./VHDLFormatter"; +import { RemoveAsserts } from "./VHDLFormatter"; +import { ApplyNoNewLineAfter } from "./VHDLFormatter"; var showUnitTests = true;//window.location.href.indexOf("http") < 0; if (showUnitTests) { UnitTest(); UnitTestIndentDecode(); + UnitTestRemoveAsserts(); + UnitTestApplyNoNewLineAfter(); } interface Function { readonly name: string; } +function UnitTestApplyNoNewLineAfter() { + console.log("=== ApplyNoNewLineAfter ==="); + let input: Array = ["a;", "b;"]; + let expected: Array = ["a;@@singleline","b;@@singleline"]; + let parameters: Array = [";"]; + UnitTest4(ApplyNoNewLineAfter, "one blankspace", parameters, input, expected); + + input = ["a;", "b THEN", "c"]; + expected = ["a;@@singleline", "b THEN@@singleline", "c"]; + parameters = [";", "then"]; + UnitTest4(ApplyNoNewLineAfter, "one blankspace", parameters, input, expected); +} + +function UnitTestRemoveAsserts() { + console.log("=== RemoveAsserts ==="); + let input: Array = ["ASSERT a;"]; + let expected: Array = [""]; + UnitTest3(RemoveAsserts, "one assert", input, expected); + + input = ["ASSERT a", "b;", "c"]; + expected = ["", "", "c"]; + UnitTest3(RemoveAsserts, "multiline assert", input, expected); +} + function UnitTestIndentDecode() { console.log("=== IndentDecode ==="); UnitTest2(indentDecode, "one blankspace", " ", "one blankspace"); @@ -31,8 +59,34 @@ function assert(testName, expected, actual, message?) { } } +function assertArray(testName, expected, actual, message?) { + var result = CompareArray(actual, expected); + if (result != true) { + console.log(testName + " failed: " + result); + } + else { + //console.log(testName + " pass"); + } +} + type StringCallback = (text: string) => string; +type ArrayCallback = (arr: Array) => void; + +type Array2Callback = (arr: Array, parameters: Array) => void; + +function UnitTest4(func: Array2Callback, testName: string, parameters: Array, inputs: Array, expected: Array) { + let actual = JSON.parse(JSON.stringify(inputs)); + func(actual, parameters); + assertArray(testName, expected, actual); +} + +function UnitTest3(func: ArrayCallback, testName: string, inputs: Array, expected: Array) { + let actual = JSON.parse(JSON.stringify(inputs)); + func(actual); + assertArray(testName, expected, actual); +} + function UnitTest2(func: StringCallback, testName: string, inputs, expected: string) { let actual: string = func(inputs); assert(testName, expected, actual); @@ -44,18 +98,36 @@ function deepCopy(objectToCopy: BeautifierSettings): BeautifierSettings { function UnitTest() { let new_line_after_symbols: NewLineSettings = new NewLineSettings(); - new_line_after_symbols.newLineAfter = ["Then", ";"]; + new_line_after_symbols.newLineAfter = ["then", ";"]; + new_line_after_symbols.noNewLineAfter = ["port", "generic"]; let settings: BeautifierSettings = new BeautifierSettings(false, false, false, false, false, "uppercase", " ", new_line_after_symbols); let input = "architecture TB of TB_CPU is\r\n component CPU_IF\r\n port -- port list\r\n end component;\r\n signal CPU_DATA_VALID: std_ulogic;\r\n signal CLK, RESET: std_ulogic := '0';\r\n constant PERIOD : time := 10 ns;\r\n constant MAX_SIM: time := 50 * PERIOD;\r\n begin\r\n -- concurrent statements\r\n end TB;" let expected = "ARCHITECTURE TB OF TB_CPU IS\r\n COMPONENT CPU_IF\r\n PORT -- port list\r\n END COMPONENT;\r\n SIGNAL CPU_DATA_VALID : std_ulogic;\r\n SIGNAL CLK, RESET : std_ulogic := '0';\r\n CONSTANT PERIOD : TIME := 10 ns;\r\n CONSTANT MAX_SIM : TIME := 50 * PERIOD;\r\nBEGIN\r\n -- concurrent statements\r\nEND TB;"; let actual = beautify(input, settings); - console.log("General", actual == expected); + console.log("General", CompareString(actual, expected)); let newSettings = deepCopy(settings); newSettings.RemoveComments = true; expected = "ARCHITECTURE TB OF TB_CPU IS\r\n COMPONENT CPU_IF\r\n PORT \r\n END COMPONENT;\r\n SIGNAL CPU_DATA_VALID : std_ulogic;\r\n SIGNAL CLK, RESET : std_ulogic := '0';\r\n CONSTANT PERIOD : TIME := 10 ns;\r\n CONSTANT MAX_SIM : TIME := 50 * PERIOD;\r\nBEGIN\r\nEND TB;"; actual = beautify(input, newSettings); - console.log("Remove comments", actual == expected); + console.log("Remove comments", CompareString(actual, expected)); + + let new_line_after_symbols_2: NewLineSettings = new NewLineSettings(); + new_line_after_symbols_2.newLineAfter = []; + new_line_after_symbols_2.noNewLineAfter = ["then", ";", "generic", "port"]; + newSettings = deepCopy(settings); + newSettings.NewLineSettings = new_line_after_symbols_2; + expected = "a; b; c;"; + input = "a; \r\nb;\r\n c;" + actual = beautify(input, newSettings); + console.log("Remove line after ;", CompareString(actual, expected)); + + newSettings = deepCopy(settings); + newSettings.RemoveAsserts = true; + input = "architecture arch of ent is\r\nbegin\r\n assert False report sdfjcsdfcsdj;\r\n assert False report sdfjcsdfcsdj severity note;\r\nend architecture;"; + expected = "ARCHITECTURE arch OF ent IS\r\nBEGIN\r\nEND ARCHITECTURE;" + actual = beautify(input, newSettings); + console.log("Remove asserts", CompareString(actual, expected)); input = "entity TB_DISPLAY is\r\n-- port declarations\r\nend TB_DISPLAY;\r\n\r\narchitecture TEST of TB_DISPLAY is\r\n-- signal declarations\r\nbegin\r\n-- component instance(s)\r\nend TEST;"; expected = "ENTITY TB_DISPLAY IS\r\n -- port declarations\r\nEND TB_DISPLAY;\r\n\r\nARCHITECTURE TEST OF TB_DISPLAY IS\r\n -- signal declarations\r\nBEGIN\r\n -- component instance(s)\r\nEND TEST;"; @@ -106,12 +178,12 @@ function UnitTest() { input = "port (a : in std_logic;\r\n b : in std_logic;\r\n);"; expected = "PORT \r\n(\r\n a : IN std_logic;\r\n b : IN std_logic;\r\n);"; - let new_line_after_symbols_2: NewLineSettings = new NewLineSettings(); - new_line_after_symbols_2.newLineAfter = ["Then", ";", "generic", "port"]; + new_line_after_symbols_2 = new NewLineSettings(); + new_line_after_symbols_2.newLineAfter = ["then", ";", "generic", "port"]; newSettings = deepCopy(settings); newSettings.NewLineSettings = new_line_after_symbols_2; actual = beautify(input, newSettings); - console.log("New line aster PORT", CompareString(actual, expected)); + console.log("New line after PORT", CompareString(actual, expected)); input = "component a is\r\nport( Data : inout Std_Logic_Vector(7 downto 0););\r\nend component a;"; expected = "COMPONENT a IS\r\n PORT (Data : INOUT Std_Logic_Vector(7 DOWNTO 0););\r\nEND COMPONENT a;"; @@ -146,11 +218,38 @@ function CompareString(actual: string, expected: string) { for (var i = 0; i < l; i++) { if (actual[i] != expected[i]) { var toEnd = Math.min(i + 50, l); - return '\ndifferent at ' + i.toString() + '\nactual: "\n' + actual.substring(i, toEnd) + '\nexpected: "\n' + expected.substring(i, toEnd) + '"' + "\nactual: \n" + actual; + return '\ndifferent at ' + i.toString() + + '\nactual: "\n' + actual.substring(i, toEnd) + + '\nexpected: "\n' + expected.substring(i, toEnd) + '"\n---' + + "\nactual (full): \n" + actual + "\n---" + + "\nexpected (full): \n" + expected + "\n====\n"; } } if (actual != expected) { return 'actual: \n"' + actual + '"\nexpected: \n"' + expected + '"'; } return true; +} + +function CompareArray(actual: Array, expected: Array) { + var l = Math.min(actual.length, expected.length); + let result: string = ""; + for (var i = 0; i < l; i++) { + if (actual[i] != expected[i]) { + result += CompareString(actual[i], expected[i]) + "\n"; + } + } + if (actual.length > expected.length) { + result += "actual has more items"; + for (var i = expected.length; i < actual.length; i++) { + result += "actual[" + i + "] = " + actual[i]; + } + } + else if (actual.length < expected.length) { + result += "expected has more items"; + for (var i = actual.length; i < expected.length; i++) { + result += "expected[" + i + "] = " + expected[i]; + } + } + return true; } \ No newline at end of file