summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbscan <10503608+bscan@users.noreply.github.com>2023-10-08 13:51:25 -0400
committerbscan <10503608+bscan@users.noreply.github.com>2023-10-08 13:51:25 -0400
commit8dbe20898d8e3ae0bada281b793574319ded2bea (patch)
tree464f5ec5211a727be95e064e08ba038abc68ce6d
parentb10cf7b92e4cd133acf8e117f891f2bbfe759589 (diff)
downloadPerlNavigator-8dbe20898d8e3ae0bada281b793574319ded2bea.zip
Adding parsing modes. Speeds up parsing if we don't need end lines for subs or packages.
-rw-r--r--server/src/diagnostics.ts4
-rw-r--r--server/src/parser.ts44
-rw-r--r--server/src/symbols.ts4
-rw-r--r--server/src/types.ts5
-rw-r--r--testWorkspace/mainTest.pl2
5 files changed, 35 insertions, 24 deletions
diff --git a/server/src/diagnostics.ts b/server/src/diagnostics.ts
index ce8d4d5..f3d1158 100644
--- a/server/src/diagnostics.ts
+++ b/server/src/diagnostics.ts
@@ -2,7 +2,7 @@ import {
Diagnostic,
DiagnosticSeverity,
} from 'vscode-languageserver/node';
-import { NavigatorSettings, CompilationResults, PerlDocument } from "./types";
+import { ParseType, NavigatorSettings, CompilationResults, PerlDocument } from "./types";
import {
WorkspaceFolder
} from 'vscode-languageserver-protocol';
@@ -26,7 +26,7 @@ export async function perlcompile(textDocument: TextDocument, workspaceFolders:
perlParams = perlParams.concat(getInquisitor());
nLog("Starting perl compilation check with the equivalent of: " + settings.perlPath + " " + perlParams.join(" ") + " " + filePath, settings);
- const parsingPromise = parseDocument(textDocument);
+ const parsingPromise = parseDocument(textDocument, ParseType.shallow);
let output: string;
let stdout: string;
diff --git a/server/src/parser.ts b/server/src/parser.ts
index 05e0b4f..346f12f 100644
--- a/server/src/parser.ts
+++ b/server/src/parser.ts
@@ -1,7 +1,7 @@
import { start } from "repl";
-import { PerlDocument, PerlElem, PerlImport, PerlSymbolKind} from "./types";
+import { PerlDocument, PerlElem, PerlImport, PerlSymbolKind, ParseType} from "./types";
import { TextDocument } from 'vscode-languageserver-textdocument';
import Uri from 'vscode-uri';
import fs = require('fs');
@@ -29,11 +29,11 @@ function init_doc (textDocument: TextDocument): PerlDocument {
return perlDoc;
}
-export async function parseDocument(textDocument: TextDocument ): Promise<PerlDocument> {
+export async function parseDocument(textDocument: TextDocument, parseType: ParseType ): Promise<PerlDocument> {
let perlDoc = init_doc(textDocument);
- const codeArray = await cleanCode(textDocument, perlDoc);
+ const codeArray = await cleanCode(textDocument, perlDoc, parseType);
let sActiveOO: Map<string, boolean> = new Map(); // Keep track of OO frameworks in use to keep down false alarms on field vs has vs attr
// Loop through file
const file = Uri.parse(textDocument.uri).fsPath;
@@ -110,20 +110,20 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
else if ((match = stmt.match(/^package\s+([\w:]+)/))) {
// Get name of the package
package_name = match[1];
- const endLine = PackageEndLine(line_num, codeArray);
+ const endLine = PackageEndLine(line_num, codeArray, parseType);
MakeElem(package_name, PerlSymbolKind.Package, '', file, package_name, line_num, perlDoc, endLine);
}
// This is a class decoration for Object::Pad, Corinna, or Moops
else if((match = stmt.match(/^class\s+([\w:]+)/))){
let class_name = match[1];
- const endLine = PackageEndLine(line_num, codeArray);
+ const endLine = PackageEndLine(line_num, codeArray, parseType);
MakeElem(class_name, PerlSymbolKind.Class, '', file, package_name, line_num, perlDoc, endLine);
}
else if((match = stmt.match(/^role\s+([\w:]+)/))){
const roleName = match[1];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(roleName, PerlSymbolKind.Role, '', file, package_name, line_num, perlDoc, endLine);
}
@@ -135,7 +135,7 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
const subName = match[2];
const signature = match[4];
const kind = (match[1] === 'method' || match[3]) ? PerlSymbolKind.LocalMethod : PerlSymbolKind.LocalSub;
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(subName, kind, '', file, package_name, line_num, perlDoc, endLine);
// Match the after the sub declaration and before the start of the actual sub for signatures (if any)
@@ -153,7 +153,7 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
// Phaser block
else if ((match = stmt.match(/^(BEGIN|INIT|CHECK|UNITCHECK|END)\s*\{/))) {
const phaser = match[1];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(phaser, PerlSymbolKind.Phaser, '', file, package_name, line_num, perlDoc, endLine);
}
@@ -161,7 +161,7 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
// Label line
else if ((match = stmt.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:[^:].*{\s*$/))) {
const label = match[1];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(label, PerlSymbolKind.Label, '', file, package_name, line_num, perlDoc, endLine);
}
@@ -212,7 +212,7 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
sActiveOO.set(importPkg, true);
}
- else if(MatchDancer(stmt, line_num, sActiveOO, file, package_name, perlDoc, codeArray)) {
+ else if(MatchDancer(stmt, line_num, sActiveOO, file, package_name, perlDoc, codeArray, parseType)) {
// Self contained
}
@@ -227,7 +227,7 @@ export async function parseDocument(textDocument: TextDocument ): Promise<PerlDo
function MatchDancer(stmt: string, line_num: number, sActiveOO: Map<string, boolean>,
- file: string, package_name: string, perlDoc: PerlDocument, codeArray: string[]): boolean {
+ file: string, package_name: string, perlDoc: PerlDocument, codeArray: string[], parseType: ParseType): boolean {
if(!(sActiveOO.has("Dancer") || sActiveOO.has("Dancer2") || sActiveOO.has("Mojolicious::Lite"))) {
@@ -243,7 +243,7 @@ function MatchDancer(stmt: string, line_num: number, sActiveOO: Map<string, bool
// TODO: Put this back
requests = requests.replace(/['"\s\n]+/g, "");
route = `${requests} ${route}`;
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(route, PerlSymbolKind.HttpRoute, '', file, package_name, line_num, perlDoc, endLine);
// TODO: I think this is a bug with [^\2] not working
@@ -252,17 +252,17 @@ function MatchDancer(stmt: string, line_num: number, sActiveOO: Map<string, bool
} else if ((match = stmt.match(/^(get|any|post|put|patch|delete|del|options|ajax|before_route)\s+(?:[\s\w,\[\]'"]+=>\s*)?(['"])([^'"]+)\2\s*=>\s*sub/))) {
// Routing paths
let route = match[1] + " " + match[3];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(route, PerlSymbolKind.HttpRoute, '', file, package_name, line_num, perlDoc, endLine);
} else if ((match = stmt.match(/^(get|any|post|put|patch|delete|del|options|ajax|before_route)\s+(qr\{[^\}]+\})\s+\s*=>\s*sub/))) {
// Regexp routing paths
let route = match[1] + " " + match[2];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(route, PerlSymbolKind.HttpRoute, '', file, package_name, line_num, perlDoc, endLine);
} else if ((match = stmt.match(/^(?:hook)\s+(['"]|)(\w+)\1\s*=>\s*sub/))) {
// Hooks
let hook = match[2];
- const endLine = SubEndLine(line_num, codeArray);
+ const endLine = SubEndLine(line_num, codeArray, parseType);
MakeElem(hook, PerlSymbolKind.HttpRoute, '', file, package_name, line_num, perlDoc, endLine);
} else {
return false;
@@ -271,7 +271,7 @@ function MatchDancer(stmt: string, line_num: number, sActiveOO: Map<string, bool
}
-async function cleanCode(textDocument: TextDocument, perlDoc: PerlDocument): Promise<string[]> {
+async function cleanCode(textDocument: TextDocument, perlDoc: PerlDocument, parseType: ParseType): Promise<string[]> {
let code = textDocument.getText();
const codeArray = code.split("\n");
@@ -295,7 +295,10 @@ async function cleanCode(textDocument: TextDocument, perlDoc: PerlDocument): Pro
codeClean.push(stmt);
}
- codeClean = await stripCommentsAndQuotes(codeClean);
+ if(parseType == ParseType.deep){
+ // If only doing shallow parsing, we don't need to strip {} or find start-end points of subs
+ codeClean = await stripCommentsAndQuotes(codeClean);
+ }
return codeClean;
}
@@ -362,10 +365,11 @@ function MakeElem(name: string, type: PerlSymbolKind | 'u' | '2',
-function SubEndLine (start_line: number, code: String[], rFilter: RegExp | null = null) : number {
+function SubEndLine (start_line: number, code: String[], parseType: ParseType, rFilter: RegExp | null = null) : number {
let pos = 0;
let found = false;
+ if(parseType == ParseType.shallow) return start_line;
for (let i = start_line; i < code.length; i++) {
// Perhaps limit the max depth?
@@ -398,8 +402,10 @@ function SubEndLine (start_line: number, code: String[], rFilter: RegExp | null
}
-function PackageEndLine (start_line: number, code: String[]) {
+function PackageEndLine (start_line: number, code: String[], parseType: ParseType) {
+ if(parseType == ParseType.shallow) return start_line;
+
if (code[start_line].match(/(class|package)[^#]+;/)){
// Single line package definition.
diff --git a/server/src/symbols.ts b/server/src/symbols.ts
index 70e46ba..4de961d 100644
--- a/server/src/symbols.ts
+++ b/server/src/symbols.ts
@@ -10,7 +10,7 @@ import {
TextDocument
} from 'vscode-languageserver-textdocument';
-import { PerlDocument, PerlElem, PerlSymbolKind } from "./types";
+import { ParseType, PerlDocument, PerlElem, PerlSymbolKind } from "./types";
import Uri from 'vscode-uri';
import { realpathSync, existsSync } from 'fs';
import { Console } from 'console';
@@ -18,7 +18,7 @@ import { parseDocument } from './parser';
export async function getSymbols (textDocument: TextDocument, uri: string ): Promise<SymbolInformation[]> {
- let perlDoc = await parseDocument(textDocument);
+ let perlDoc = await parseDocument(textDocument, ParseType.deep);
let symbols: SymbolInformation[] = [];
perlDoc.elems?.forEach((elements: PerlElem[], elemName: string) => {
diff --git a/server/src/types.ts b/server/src/types.ts
index f8ab5f8..ab1ecee 100644
--- a/server/src/types.ts
+++ b/server/src/types.ts
@@ -63,6 +63,11 @@ export interface PerlDocument {
uri: string;
}
+export enum ParseType {
+ deep,
+ shallow
+}
+
export interface CompilationResults {
diags: Diagnostic[],
perlDoc: PerlDocument,
diff --git a/testWorkspace/mainTest.pl b/testWorkspace/mainTest.pl
index 491fdaf..02136f4 100644
--- a/testWorkspace/mainTest.pl
+++ b/testWorkspace/mainTest.pl
@@ -116,7 +116,7 @@ my $otherObj = MyLib::MyOtherClass->new();
$otherObj->unique_method_name();
$otherObj->duplicate_method_name();
-my $unknownObj = $otherObj; # Type hints: $unknownObj2 isa MyLib::MyOtherClass
+my $unknownObj = $otherObj; # Type hints: $unknownObj isa MyLib::MyOtherClass
$unknownObj->duplicate_method_name();
my $mooObj = MyLib::MooClass->new();