Skip to content

Commit

Permalink
General bug fixes for P1 and P2
Browse files Browse the repository at this point in the history
- Repair filename validation in object includes - make checking the same as PNut/Propeller Tool
- Ensure no parser Error/Warning/Information messages are returned when **maxNumberOfReportedIssues** is set to zero
- P1 repair hover detection for object#constant references
- P2 add basic hover text for Streamer Constants
- P1/P2 CON enhance parsing of operators used within RHS of assignment
- P1/P2 enhance parsing when {comment} used within the line being parsed
- P2 OBJ enhance parsing of object override values
- P1/P2 PUB/PRI enhance parsing left hand side of assignments
  • Loading branch information
ironsheep committed Oct 31, 2023
1 parent 475f62f commit fac4ff6
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 173 deletions.
13 changes: 13 additions & 0 deletions spin2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ Possible next additions:
- Add new-file templates as Snippets
- Add additional Snippets as the community identifies them

## [2.2.1] 2023-10-30

General bug fixes for P1 and P2

- Repair filename validation in object includes - make checking the same as PNut/Propeller Tool
- Ensure no parser Error/Warning/Information messages are returned when **maxNumberOfReportedIssues** is set to zero
- P1 repair hover detection for object#constant references
- P2 add basic hover text for Streamer Constants
- P1/P2 CON enhance parsing of operators used within RHS of assignment
- P1/P2 enhance parsing when {comment} used within the line being parsed
- P2 OBJ enhance parsing of object override values
- P1/P2 PUB/PRI enhance parsing left hand side of assignments

## [2.2.0] 2023-10-28

- Awaken **Show Definitions of a Symbol feature** supporting peek at and go-to definition(s). (returns one or more matching symbols found in current open find and included objects)
Expand Down
8 changes: 7 additions & 1 deletion spin2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
"name": "spin2",
"displayName": "Spin2",
"description": "P1 and P2 Spin/Pasm Syntax/Semantic Highlighting w/Code Outline, Object Outline and Custom tabbing support",
"icon": "images/Propeller.ico",
"author": "IronSheep",
"license": "MIT",
"version": "2.2.0",
"version": "2.2.1",
"repository": {
"type": "git",
"url": "https://github.com/ironsheep/P2-vscode-langserv-extension"
Expand All @@ -13,6 +14,11 @@
"url": "https://github.com/ironsheep/P2-vscode-langserv-extension/issues"
},
"publisher": "IronSheepProductionsLLC",
"preview": true,
"galleryBanner": {
"color": "#003060",
"theme": "dark"
},
"categories": [],
"keywords": [
"spin",
Expand Down
8 changes: 7 additions & 1 deletion spin2/scripts/LIVE-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
"name": "spin2",
"displayName": "Spin2",
"description": "P1 and P2 Spin/Pasm Syntax/Semantic Highlighting w/Code Outline, Object Outline and Custom tabbing support",
"icon": "images/Propeller.ico",
"author": "IronSheep",
"license": "MIT",
"version": "2.2.0",
"version": "2.2.1",
"repository": {
"type": "git",
"url": "https://github.com/ironsheep/P2-vscode-langserv-extension"
Expand All @@ -13,6 +14,11 @@
"url": "https://github.com/ironsheep/P2-vscode-langserv-extension/issues"
},
"publisher": "IronSheepProductionsLLC",
"preview": true,
"galleryBanner": {
"color": "#003060",
"theme": "dark"
},
"categories": [],
"keywords": [
"spin",
Expand Down
3 changes: 2 additions & 1 deletion spin2/scripts/TEST-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "P1 and P2 Spin/Pasm Syntax/Semantic Highlighting w/Code Outline, Object Outline and Custom tabbing support",
"author": "IronSheep",
"license": "MIT",
"version": "2.1.1",
"version": "2.2.1",
"repository": {
"type": "git",
"url": "https://github.com/ironsheep/P2-vscode-langserv-extension"
Expand Down Expand Up @@ -87,6 +87,7 @@
"scope": "resource",
"type": "number",
"default": 100,
"minimum": 0,
"description": "Controls the maximum number of issues reported by the spin2 server (for each file.)"
},
"spinExtension.trace.server": {
Expand Down
15 changes: 10 additions & 5 deletions spin2/server/src/parser/lsp.textDocument.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
import * as lsp from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument";

export function GetWordRangeAtPosition(lineText: string, position: lsp.Position): lsp.Range {
export function GetWordRangeAtPosition(lineText: string, position: lsp.Position, isSpin1File: boolean = false): lsp.Range {
// return rage of word found at position
let startIndex: number = position.character;
let endIndex: number = position.character;
const wordEndCharacterSet: string = "\"'[]()<> @\t,+-*/=:";
const wordEndCharacterSetP1: string = "\"'[]()<> |^&@\t,+-*/\\=";
const wordEndCharacterSetP2: string = "\"'[]()<> |^&#@\t,+-*/\\=:";
const checkCharSet: string = isSpin1File ? wordEndCharacterSetP1 : wordEndCharacterSetP2;

// back up to start of word, mark start
let bStartFound: boolean = false;
for (let index = startIndex; index > 0; index--) {
if (wordEndCharacterSet.includes(lineText.charAt(index - 1))) {
if (checkCharSet.includes(lineText.charAt(index - 1))) {
startIndex = index;
bStartFound = true;
break;
Expand All @@ -21,18 +24,20 @@ export function GetWordRangeAtPosition(lineText: string, position: lsp.Position)
if (!bStartFound) {
startIndex = 0;
}

// go forward to end of word, mark end
let bEndFound: boolean = false;
for (let index = endIndex; index < lineText.length - 1; index++) {
if (wordEndCharacterSet.includes(lineText.charAt(index + 1))) {
if (checkCharSet.includes(lineText.charAt(index + 1))) {
endIndex = index + 1;
bEndFound = true;
break;
}
}
if (!bEndFound) {
endIndex = lineText.length - 1;
endIndex = lineText.length;
}

// returning findings
let wordRange: lsp.Range = { start: { line: position.line, character: startIndex }, end: { line: position.line, character: endIndex } };
return wordRange;
Expand Down
70 changes: 45 additions & 25 deletions spin2/server/src/parser/spin.extension.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,51 @@ export class ExtensionUtils {
// PUBLIC Methods
//
public adjustWordPosition(document: TextDocument, position: lsp.Position, isInBlockComment: boolean, inPasmCodeStatus: boolean): [boolean, string, string, lsp.Position] {
const lineText = DocumentLineAt(document, position);
const lineText = DocumentLineAt(document, position).trimEnd();
const P2_LOCAL_LABEL_PREFIX: string = ".";
const P1_LOCAL_LABEL_PREFIX: string = ":";
const spin1File: boolean = isSpin1File(document.uri);
const localPasmLablePrefix: string = spin1File ? P1_LOCAL_LABEL_PREFIX : P2_LOCAL_LABEL_PREFIX;
const spinControlFlowKeywords: string[] = spin1File ? this.spin1ControlFlowKeywords : this.spin2ControlFlowKeywords;
let wordRange: lsp.Range | undefined = GetWordRangeAtPosition(lineText, position);
let wordRange: lsp.Range | undefined = GetWordRangeAtPosition(lineText, position, spin1File);
if (inPasmCodeStatus) {
// do fixup for Spin2 pasm local labels
const P2_LOCAL_LABEL_PREFIX: string = ".";
const P1_LOCAL_LABEL_PREFIX: string = ":";
if (wordRange?.start.character > 0 && (lineText.charAt(wordRange.start.character - 1) == P2_LOCAL_LABEL_PREFIX || lineText.charAt(wordRange.start.character - 1) == P1_LOCAL_LABEL_PREFIX)) {
if (wordRange?.start.character > 0 && lineText.charAt(wordRange.start.character - 1) == localPasmLablePrefix) {
const newStart: lsp.Position = PositionTranslate(wordRange.start, 0, -1);
wordRange = { start: { line: newStart.line, character: newStart.character }, end: { line: wordRange?.end.line, character: wordRange?.end.character } };
}
}
const tmpWord: string = wordRange ? document.getText(wordRange) : "";
const tmpWord: string = wordRange ? document.getText(wordRange) : ""; // trim() shouldn't be needed!!!
this._logMessage(`+ sp2Utils: adjustWordPosition() orig tmpWord=[${tmpWord}](${tmpWord.length}), isInBlockComment=(${isInBlockComment})`);
let lineParts: string[] = [tmpWord];
let rangeDots: boolean = false;
if (tmpWord.includes("..")) {
lineParts = tmpWord.split("..");
rangeDots = true;
} else if (tmpWord.includes(".")) {
lineParts = tmpWord.split(".");
if (!tmpWord.charAt(0).match(/[a-zA-Z_]/) && !tmpWord.startsWith(localPasmLablePrefix)) {
lineParts = [];
} else {
if (tmpWord.includes("..")) {
lineParts = tmpWord.split("..");
rangeDots = true;
} else if (tmpWord.includes(".") && !tmpWord.startsWith(".")) {
lineParts = tmpWord.split(".");
} else if (tmpWord.includes(",")) {
lineParts = tmpWord.split(",");
} else if (spin1File) {
if (tmpWord.includes("#")) {
lineParts = tmpWord.split("#"); // in spin1 this is an object constant reference
}
} else {
if (tmpWord.startsWith("#")) {
lineParts = [tmpWord.substring(1)]; // remove leading "#"
}
}
}

// bazarre fixup of trailing whitespace
if (lineParts.length > 0 && (lineParts[0].endsWith(" ") || lineParts[0].endsWith("\t"))) {
lineParts[0] = lineParts[0].trimEnd();
}

this._logMessage(`+ sp2Utils: adjustWordPosition() tmpWord=[${tmpWord}](${tmpWord.length}), lineParts=[${lineParts}](${lineParts.length})`);
let word: string = "";
let objectRef: string = "";
switch (lineParts.length) {
Expand All @@ -96,21 +119,20 @@ export class ExtensionUtils {
}
//const word: string = lineParts.length == 1 ? lineParts[0] : "";
//const objectRef: string = "";

this._logMessage(
`+ sp2Utils: adjustWordPosition() ENTRY wordRange=[${wordRange?.start.line}:${wordRange?.start.character}-${wordRange?.end.line}:${wordRange?.end.character}], obj=[${objectRef}], word=[${word}]`
`+ sp2Utils: adjustWordPosition() wordRange=[${wordRange?.start.line}:${wordRange?.start.character}-${wordRange?.end.line}:${wordRange?.end.character}], obj=[${objectRef}], word=[${word}]`
);
// TODO: fix this for spin comments vs. // comments

const stringsFound: IPairs[] = this.getStringPairOffsets(lineText);
const ticVarsFound: IPairs[] = this.getPairOffsetsOfTicVarWraps(lineText);
//const stringsFound: IPairs[] = [];
let isPositionInComment: boolean = this.isPositionInComment(document, position, stringsFound);
if (!isPositionInComment) {
isPositionInComment = isInBlockComment;
this._logMessage(`+ sp2Utils: adjustWordPosition() (post-block): isPositionInComment=${isPositionInComment}`);
let bPositionInComment: boolean = this.isPositionInComment(lineText, position, stringsFound);
if (!bPositionInComment) {
bPositionInComment = isInBlockComment;
this._logMessage(`+ sp2Utils: adjustWordPosition() (post-block): bPositionInComment=${bPositionInComment}`);
}
if (!wordRange || this.isPositionInString(document, position, stringsFound, ticVarsFound) || isPositionInComment || word.match(/^\d+.?\d+$/) || spinControlFlowKeywords.indexOf(word) > 0) {
if (!wordRange || this.isPositionInString(lineText, position, stringsFound, ticVarsFound) || bPositionInComment || word.match(/^\d+.?\d+$/) || spinControlFlowKeywords.indexOf(word) > 0) {
this._logMessage(`+ sp2Utils: adjustWordPosition() EXIT false`);
return [false, null!, null!, null!];
}
Expand All @@ -122,9 +144,8 @@ export class ExtensionUtils {
return [true, objectRef, word, position];
}

public isPositionInString(document: TextDocument, position: lsp.Position, stringsInLine: IPairs[], ticVarsInLine: IPairs[]): boolean {
public isPositionInString(lineText: string, position: lsp.Position, stringsInLine: IPairs[], ticVarsInLine: IPairs[]): boolean {
let inStringStatus: boolean = false;
const lineText = DocumentLineAt(document, position);
let inTicVar: boolean = false;
if (ticVarsInLine.length > 0) {
for (let ticVarIdx = 0; ticVarIdx < ticVarsInLine.length; ticVarIdx++) {
Expand All @@ -147,16 +168,15 @@ export class ExtensionUtils {
}
}

//this._logMessage(`+ sp2Utils: isPositionInString() = EXIT w/${inStringStatus}`);
this._logMessage(`+ sp2Utils: isPositionInString() = EXIT w/${inStringStatus}`);
return inStringStatus;
}

public isPositionInComment(document: TextDocument, position: lsp.Position, stringsInLine: IPairs[]): boolean {
public isPositionInComment(lineText: string, position: lsp.Position, stringsInLine: IPairs[]): boolean {
let inCommentStatus: boolean = false;
const lineTextUntrim = DocumentLineAt(document, position);
const lineText = lineTextUntrim.trim();
let inString: boolean = false;
// if entire line is comment
this._logMessage(`+ sp2Utils: isPositionInComment() lineText=[${lineText}](${lineText.length})`);
if (lineText.startsWith("'") || lineText.startsWith("{")) {
inCommentStatus = true;
} else {
Expand Down Expand Up @@ -213,7 +233,7 @@ export class ExtensionUtils {
}
}

//this._logMessage(`+ sp2Utils: _getStringPairOffsets() - found ${findings.length} pair(s)`);
this._logMessage(`+ sp2Utils: _getStringPairOffsets() - found ${findings.length} pair(s)`);
return findings;
}

Expand Down
44 changes: 23 additions & 21 deletions spin2/server/src/parser/spin.semantic.findings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,32 +244,34 @@ export class DocumentFindings {
public allDiagnosticMessages(messageCountMax: number): Diagnostic[] {
const formattedMessages: Diagnostic[] = [];
// return a list of the messages we have
const sortReportsByLineChar = (n1: DiagnosticReport, n2: DiagnosticReport) => {
if (n1.location().start.line > n2.location().start.line) {
return 1;
}
if (messageCountMax > 0) {
const sortReportsByLineChar = (n1: DiagnosticReport, n2: DiagnosticReport) => {
if (n1.location().start.line > n2.location().start.line) {
return 1;
}

if (n1.location().start.line < n2.location().start.line) {
return -1;
}
if (n1.location().start.line < n2.location().start.line) {
return -1;
}

if (n1.location().start.character > n2.location().start.character) {
return 1;
}
if (n1.location().start.character > n2.location().start.character) {
return 1;
}

if (n1.location().start.character < n2.location().start.character) {
return -1;
}
if (n1.location().start.character < n2.location().start.character) {
return -1;
}

return 0;
};
return 0;
};

const sortedReports: DiagnosticReport[] = this.diagnosticMessages.sort(sortReportsByLineChar);
const reducedReports = this._deDupeReports(sortedReports, messageCountMax); //sortedReports; //
for (let index = 0; index < reducedReports.length; index++) {
const report = reducedReports[index];
const lspDiag: Diagnostic = Diagnostic.create(report.location(), report.message(), report.severity());
formattedMessages.push(lspDiag);
const sortedReports: DiagnosticReport[] = this.diagnosticMessages.sort(sortReportsByLineChar);
const reducedReports = this._deDupeReports(sortedReports, messageCountMax); //sortedReports; //
for (let index = 0; index < reducedReports.length; index++) {
const report = reducedReports[index];
const lspDiag: Diagnostic = Diagnostic.create(report.location(), report.message(), report.severity());
formattedMessages.push(lspDiag);
}
}
this._logMessage(`- allDiagnosticMessages(${messageCountMax}) - returns ${formattedMessages.length} messages`);
return formattedMessages;
Expand Down
26 changes: 13 additions & 13 deletions spin2/server/src/parser/spin1.documentSemanticParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -972,9 +972,12 @@ export class Spin1DocumentSemanticParser {
if (fileName) {
const filenameNoQuotes: string = fileName.replace(/\"/g, "");
const searchFilename: string = `\"${filenameNoQuotes}`;
const hasPathSep: boolean = filenameNoQuotes.includes("/");
const nameOffset: number = line.indexOf(searchFilename, startingOffset);
const logCtx: Context | undefined = this.spin1DebugLogEnabled ? this.ctx : undefined;
if (!fileInDirExists(this.directory, filenameNoQuotes, logCtx)) {
if (hasPathSep) {
this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + filenameNoQuotes.length, eSeverity.Error, `P1 spin Invalid filename character "/" in [${filenameNoQuotes}]`);
} else if (!fileInDirExists(this.directory, filenameNoQuotes, logCtx)) {
this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + fileName.length, eSeverity.Error, `Missing P1 Data file [${fileName}]`);
}
}
Expand All @@ -983,20 +986,16 @@ export class Spin1DocumentSemanticParser {
private _ensureObjectFileExists(fileName: string | undefined, lineIdx: number, line: string, startingOffset: number) {
if (fileName) {
const filenameNoQuotes: string = fileName.replace(/\"/g, "");
const hasSuffix: boolean = filenameNoQuotes.includes(".spin");
const hasSuffix: boolean = filenameNoQuotes.endsWith(".spin");
const hasPathSep: boolean = filenameNoQuotes.includes("/");
const fileWithExt = `${filenameNoQuotes}.spin`;
const nameOffset: number = line.indexOf(filenameNoQuotes, startingOffset);
const logCtx: Context | undefined = this.spin1DebugLogEnabled ? this.ctx : undefined;
if (hasSuffix) {
this.semanticFindings.pushDiagnosticMessage(
lineIdx,
nameOffset,
nameOffset + fileName.length,
eSeverity.Error,
`Invalid P1 Object filename [${filenameNoQuotes}], file extension is NOT allowed`
);
} else if (!fileInDirExists(this.directory, fileWithExt, logCtx)) {
this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + fileName.length, eSeverity.Error, `Missing P1 Object file [${fileName}.spin]`);
const checkFilename: string = hasSuffix ? filenameNoQuotes : fileWithExt;
if (hasPathSep) {
this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + filenameNoQuotes.length, eSeverity.Error, `P1 spin Invalid filename character "/" in [${filenameNoQuotes}]`);
} else if (!fileInDirExists(this.directory, checkFilename, logCtx)) {
this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + filenameNoQuotes.length, eSeverity.Error, `Missing P1 Object file [${filenameNoQuotes}]`);
}
}
}
Expand Down Expand Up @@ -1483,7 +1482,7 @@ export class Spin1DocumentSemanticParser {

let lineParts: string[] = this.parseUtils.getNonWhiteDataInitLineParts(dataValueInitStr);
const argumentStartIndex: number = this.parseUtils.isDatStorageType(lineParts[0]) ? 1 : 0;
this._logDAT(" -- lineParts=[" + lineParts + "]");
this._logDAT(` -- lineParts=[${lineParts}], argumentStartIndex=[${argumentStartIndex}]`);

// process remainder of line
if (lineParts.length < 2) {
Expand Down Expand Up @@ -3079,6 +3078,7 @@ export class Spin1DocumentSemanticParser {
}
return nonCommentLHSStr;
}

private _tokenString(aToken: IParsedToken, line: string): string {
let varName: string = line.substr(aToken.startCharacter, aToken.length);
let desiredInterp: string =
Expand Down
Loading

0 comments on commit fac4ff6

Please sign in to comment.