Skip to content

Commit

Permalink
v2.0.7 release (#106)
Browse files Browse the repository at this point in the history
* RegEx fix for labels with leading spaces.

* 98-Issue linting with multiple levels of quoting

* RegEx improvement for quoted strings

* Replace parenthesis and quoted strings with empty ones.
- Removed repetitive Trim()s
- Removed unnecessary RegEx tests
- Simplified line split on semicolon due to above changes.
- Results: Faster execution. Better coverage for split on semicolon

* - Cleanup lines[] array at start so repeated test/replace not needed
- Removed unnecessary trim()s
- Removed boolean equality tests. if(x.test == true) vs if(x.test)
- Fixed GOTO/GOSUB when followed by more than one space GOTO <s><s> 100

* RegEx fix-ups to support recent changes

* Corrected comment

* Linter RegEx cleanup

* FOR/NEXT tracking improvements and updated error messages
- Nested For/Next statements now validated
- NEXT with no variable is now allowed
- One line per error: Removed extraneous, repeated diagnostic messages
- Reworded / Clarified some error messages for consistency

* Minor code clean-up

* Replace char-at-a-time split on ; with split(";")

* Maintain original character spacing for Intellisense error markers
- RegEx improvements and consistency between client and server
- Improved getWord() function

* Corrected indentation for ELSE END with trailing comment (issue #45)

* Corrects Label error with GOTO/GOSUB. Issue #99
- Also now allows dotted numeric labels such as GOTO 100.5

* Revert "Corrects Label error with GOTO/GOSUB. Issue #99"

This reverts commit 68b0166.

* Inspect TM Scopes->Inspect Editor Token and Scopes

* Fix error processing customWordPath when last
line is blank. May relate to #24.

* Changed GOTO/GOSUB scope jumping message from Error to Warning

* Numerous updates related to For/Next and Label tracking
- Issue #45: Alignment of If/Else
- Issue #96: Allow periods in labels
- Issue #99: Corrected Label error with GOTO/GOSUB.
- Issue #104: Corrected For/Next with leading label
- Issue #105: Changed GOTO scope jumping message from Error to Warning
- RegEx: Label comments to include "REM, *, and !"
- NEXT can be used without FOR variable.

* Shipping 2.0.7

Co-authored-by: Kevin Powick <[email protected]>
Co-authored-by: Ian McGowan <[email protected]>
Co-authored-by: Peter Schellenbach <[email protected]>
  • Loading branch information
4 people authored Jun 11, 2020
1 parent b163f58 commit 97dea4d
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 407 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,14 @@
- Fixed bug that introduced spaces to blank lines
- Introduced webpack to bundle the extension
- Removed docs from the bundled extension (they can still be accessed online at the repo)
- Improvements to RestFS API
- Improvements to RestFS API

## 2.0.7

- Fixed a bug with the "customWordPath" option (#24)
- Fixed auto-formatting bug (#45)
- Added documentation for the RestFS API (#89)
- Fixed bug with space-prefixed labels (#96)
- Improved linting (#98)
- Improved label detection with GOTO/GOSUB (#99)
- Fixed bug with FOR/NEXT linting with labels (#104)
4 changes: 2 additions & 2 deletions Syntaxes/QM.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"name": "QM# BASIC",
"patterns": [
{
"match": "(\"([^\"]|\"\")*\")|('([^']|'')*')|(\\\\([^\\\\]|\\\\\\\\)*\\\\)",
"match": "'.*?'|\".*?\"|\\\\.*?\\\\",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
"match": "(^[0-9]+\\s)|(^[0-9]+:\\s)|(^[\\w]+:(?!=))|(^[\\w\\.\\w]+:(?!=))",
"match": "^\\s*([\\w.]+:(?!=)|[0-9.]+)",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
Expand Down
4 changes: 2 additions & 2 deletions Syntaxes/UniVerse.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"name": "MVON# BASIC",
"patterns": [
{
"match": "(\"([^\"]|\"\")*\")|('([^']|'')*')|(\\\\([^\\\\]|\\\\\\\\)*\\\\)",
"match": "'.*?'|\".*?\"|\\\\.*?\\\\",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
"match": "(^[0-9]+\\s)|(^[0-9]+:\\s)|(^[\\w]+:(?!=))|(^[\\w\\.\\w]+:(?!=))",
"match": "^\\s*([\\w.]+:(?!=)|[0-9.]+)",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
Expand Down
4 changes: 2 additions & 2 deletions Syntaxes/jBASE.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"name": "jBASE PickBASIC",
"patterns": [
{
"match": "(\"([^\"]|\"\")*\")|('([^']|'')*')|(\\\\([^\\\\]|\\\\\\\\)*\\\\)",
"match": "'.*?'|\".*?\"|\\\\.*?\\\\",
"name": "string.other.quoted-or-unquoted.jbase"
},
{
"match": "(^[0-9]+\\s)|(^[0-9]+:\\s)|(^[\\w]+:(?!=))|(^[\\w\\.\\w]+:(?!=))",
"match": "^\\s*([\\w.]+:(?!=)|[0-9.]+)",
"name": "string.other.quoted-or-unquoted.jbase"
},
{
Expand Down
4 changes: 2 additions & 2 deletions Syntaxes/mvon.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"name": "MVON# BASIC",
"patterns": [
{
"match": "(\"([^\"]|\"\")*\")|('([^']|'')*')|(\\\\([^\\\\]|\\\\\\\\)*\\\\)",
"match": "'.*?'|\".*?\"|\\\\.*?\\\\",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
"match": "(^[0-9]+)|(^[0-9]+:\\s)|(^[\\w]+:(?!=))|(^[\\w\\.\\w]+:(?!=))",
"match": "^\\s*([\\w.]+:(?!=)|[0-9.]+)",
"name": "string.other.quoted-or-unquoted.mvon"
},
{
Expand Down
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mvbasic",
"displayName": "MV Basic",
"description": "MV Basic",
"version": "2.0.6",
"version": "2.0.7",
"publisher": "mvextensions",
"license": "MIT",
"icon": "../images/mvbasic-logo.png",
Expand Down Expand Up @@ -38,4 +38,4 @@
"@types/node": "^13.13.4",
"@types/vscode": "^1.44.0"
}
}
}
128 changes: 74 additions & 54 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,13 @@ export function activate(context: vscode.ExtensionContext) {
var lines = contents.replace('\r', '').split('\n');
for (let i = 0; i < lines.length; i++) {
let parts = lines[i].split(':')
customWordDict.set(parts[0].replace("\"", "").replace("\"", ""), parts[1].replace("\"", "").replace("\"", ""))
customWordlist += parts[0].replace('"', '').replace("\"", "") + "|";
if (parts.length >= 2) {
customWordDict.set(parts[0].replace("\"", "").replace("\"", ""), parts[1].replace("\"", "").replace("\"", ""))
customWordlist += parts[0].replace("\"", '').replace("\"", "") + "|";
}
}
customWordlist = customWordlist.substr(0, customWordlist.length - 1) + ")";
if (customWordlist.length > 1)
customWordlist = customWordlist.substr(0, customWordlist.length - 1) + ")";

}

Expand Down Expand Up @@ -270,84 +273,96 @@ export function activate(context: vscode.ExtensionContext) {
var edits: vscode.TextEdit[] = []

if (formattingEnabled) {
let rBlockStart = new RegExp("^(lock |key\\(|if |commit |rollback |readnext |open |write |writeu |writev |writevu |read |readv |readu |readt |readvu |matreadu |locate |locate\\(|openseq |matread |create |readlist |openpath |find |findstr |bscan)", "i")
let rBlockCase = new RegExp("(^begin case)", "i")
let rBlockTransaction = new RegExp("(^begin transaction|^begin work)", "i")
let rBlockEndCase = new RegExp("(^end case)", "i")
let rBlockEndTransaction = new RegExp("(^end transaction|^end work)", "i")
let rBlockAlways = new RegExp("^(for |loop$|loop\\s+)", "i")
let rBlockContinue = new RegExp("(then$|else$|case$|on error$|locked$)", "i")
let rBlockEnd = new RegExp("^(end|repeat|next\\s.+)$", "i")
let rElseEnd = new RegExp("^(end else\\s.+)", "i")
let rLabel = new RegExp("(^[0-9]+\\s)|(^[0-9]+:\\s)|(^[\\w]+:)");
let rBlockStart = new RegExp("^(begin case$|lock |key\\(|if |commit |rollback |readnext |open |write |writeu |writev |writevu |read |readv |readu |readt |readvu |matreadu |locate |locate\\(|openseq |matread |create |readlist |openpath |find |findstr |bscan)", "i")
let rBlockAlways = new RegExp("^(for |loop( |$))", "i")
let rBlockContinue = new RegExp(" (then|else|case|on error|locked)$", "i")
let rBlockEnd = new RegExp("^(end|end case|next|next\\s+.+|repeat)$| repeat$", "i")
let rBlockCase = new RegExp("^begin case$", "i")
let rBlockEndCase = new RegExp("^end case$", "i")
let rBlockTransaction = new RegExp("^(begin transaction|begin work)", "i")
let rBlockEndTransaction = new RegExp("^(end transaction|end work)", "i")
let rElseEnd = new RegExp("^end else\\s+?.+?", "i")
let rLabel = new RegExp("^([\\w\\.]+:(?!=)|[0-9\\.]+)");
let rComment = new RegExp("^\\s*(\\*|!|REM\\s+?).*", "i")
let tComment = new RegExp(";\\s*(\\*|!|REM\\s+?).*", "i");
let lComment = new RegExp("(^[0-9]+\\s+\\*)|(^[0-9]+\\s+;)|(^[0-9]+\\*)|(^[0-9]+;)") // number label with comments after
let trailingComment = new RegExp("(\\*.+)|(;+)")
let spaces = " "
let lComment = new RegExp("^\\s*([\\w\\.]+:(?!=)|[0-9\\.]+)(\\s*(\\*|!|REM\\s+?).*)", "i") // a label with comments after
let qStrings = new RegExp("'.*?'|\".*?\"|\\\\.*?\\\\", "g");
let rParenthesis = new RegExp("\\(.*\\)", "g");
if (indent === undefined) { indent = 3 }
if (margin === undefined) { margin = 5 }


// first build a list of labels in the program and indentation levels
let Level = 0
var RowLevel: number[] = []
for (var i = 0; i < document.lineCount; i++) {

let curLine = document.lineAt(i);
let line = curLine.text;
if (rComment.test(line.trim()) == true) { continue }
// TODO ignore comment lines and
if (line.trim().startsWith("$")) { continue }
// remove trailing comments

if (tComment.test(line.trim()) == true) {
let comment = tComment.exec(line.trim());
line = line.trim().replace(comment[0], "");
// replace comment line with blank line
line = line.replace(rComment, "");

// remove comments after label (no semi-colon)
if (lComment.test(line)) {
let comment = lComment.exec(line);
line = comment![1];
}
lComment.lastIndex = 0;
if (lComment.test(line.trim()) === true) {
let comment = trailingComment.exec(line.trim());
if (comment != null) {
line = line.trim().replace(comment[0], "");
}

// remove trailing comments with a semi-colon
line = line.replace(tComment, "");

// replace contents of parenthesis with spaces, maintaining original
// character positions for intellisense error highlighting.
let v = rParenthesis.exec(line);
if (v !== null) {
let value = "(" + " ".repeat(v[0].length - 2) + ")";
line = line.replace(rParenthesis, value);
}

// replace contents of quoted strings with spaces, maintaining original
// character positions for intellisense error highlighting.
v = qStrings.exec(line);
if (v !== null) {
let value = "'" + " ".repeat(v[0].length - 2) + "'";
line = line.replace(qStrings, value);
}

// Trim() leading & trailing spaces
line = line.trim();

// check opening and closing block for types
// check block statements
var position = i
RowLevel[i] = Level

if (rBlockStart.test(line.trim()) == true) {
if (rBlockStart.test(line)) {
Level++
if (rBlockContinue.test(line.trim()) == false) {
if (!rBlockContinue.test(line)) {
// single line statement
Level--
}
position = i + 1
}
if (rBlockCase.test(line.trim()) == true) {
// increment 2 to cater for case statement
Level++
if (rBlockCase.test(line)) {
// increment to cater for case statement
Level++
position = i + 1
}
if (rBlockEndCase.test(line.trim()) == true) {
// decrement 2 to cater for case statement
Level--
if (rBlockEndCase.test(line)) {
// decrement to cater for case statement
Level--
}
if (rElseEnd.test(line.trim()) == true) {
if (rElseEnd.test(line)) {
// decrement 1 to cater for end else stements
Level--
}
if (rBlockTransaction.test(line.trim()) == true) {
// increment 2 to cater for case statement
if (rBlockTransaction.test(line)) {
// increment for transaction statement
Level++
position = i + 1
}
if (rBlockEndTransaction.test(line.trim()) == true) {
// decrement 2 to cater for case statement
if (rBlockEndTransaction.test(line)) {
// decrement for transaction statement
Level--
}
if (rBlockAlways.test(line.trim())) {
Expand All @@ -360,40 +375,45 @@ export function activate(context: vscode.ExtensionContext) {
}
RowLevel[position] = Level
}

// Output formatted lines
for (var i = 0; i < document.lineCount; i++) {

const line = document.lineAt(i);
let lineText = line.text.trim();

// ignore labels
if (rLabel.test(line.text.trim()) == true) { continue }
if (rLabel.test(lineText)) { continue }

var indentation = 0

if (RowLevel[i] === undefined) { continue; }

indentation = (RowLevel[i] * indent) + margin
if (new RegExp("(^case\\s)", "i").test(line.text.trim()) == true) {
if (new RegExp("(^case\\s)", "i").test(lineText)) {
indentation -= indent
}
if (new RegExp("(^while\\s|^until\\s)", "i").test(line.text.trim()) == true) {
if (new RegExp("(^while\\s|^until\\s)", "i").test(lineText)) {
indentation -= indent
}
if (new RegExp("(^end else$)", "i").test(line.text.trim()) == true) {

// remove trailing comments with a semi-colon
let tempLine = lineText.replace(tComment, "").trim();
if (new RegExp("(^end else$)", "i").test(tempLine)) {
indentation -= indent
}

var blankLine = line.text.replace(/\s/g, "")
var blankLine = lineText.replace(/\s/g, "")
if (indentation < 1 || blankLine.length == 0) {
edits.push(vscode.TextEdit.replace(line.range, line.text.trim()))
edits.push(vscode.TextEdit.replace(line.range, lineText))
}
else {
var regEx = "\\s{" + indentation + "}"
var formattedLine = new RegExp(regEx).exec(spaces)[0] + line.text.trim()
var formattedLine = " ".repeat(indentation) + lineText
var formatted = vscode.TextEdit.replace(line.range, formattedLine)
edits.push(formatted)
}
}
}

return edits
}
});
Expand Down Expand Up @@ -451,11 +471,11 @@ export function activate(context: vscode.ExtensionContext) {
}
activeEditor.setDecorations(customDecoration, customWords);
}

let api = {
getRestFS(): RestFS {
return RESTFS;
}
}
};
return api;
}
Expand Down
2 changes: 1 addition & 1 deletion doc/DeveloperIntro.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ An introduction to how syntax highlights work in VSCode: https://code.visualstud

A description of the various "scopes" typically used: https://macromates.com/manual/en/language_grammars#naming_conventions

Using "Developer: Inspect TM Scopes" to see how a particular token is interpreted. This will show both the source as well as the scope for any language elements selected.
Using "Developer: Inspect Editor Token and Scopes" to see how a particular token is interpreted. This will show both the source as well as the scope for any language elements selected.

![Dev Inspect Scopes](screenshots/devguide/dev_inspect_scopes.gif)

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mvbasic",
"displayName": "MV Basic",
"description": "MV Basic",
"version": "2.0.6",
"version": "2.0.7",
"publisher": "mvextensions",
"license": "MIT",
"icon": "images/mvbasic-logo.png",
Expand Down Expand Up @@ -341,4 +341,4 @@
"webpack-cli": "^3.3.11"
},
"dependencies": {}
}
}
4 changes: 2 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mvbasic",
"displayName": "MV Basic",
"description": "MV Basic",
"version": "2.0.6",
"version": "2.0.7",
"publisher": "mvextensions",
"license": "MIT",
"icon": "../images/mvbasic-logo.png",
Expand Down Expand Up @@ -36,4 +36,4 @@
"devDependencies": {
"@types/node": "^13.13.4"
}
}
}
Loading

0 comments on commit 97dea4d

Please sign in to comment.