diff options
author | bscan <10503608+bscan@users.noreply.github.com> | 2023-10-08 13:51:25 -0400 |
---|---|---|
committer | bscan <10503608+bscan@users.noreply.github.com> | 2023-10-08 13:51:25 -0400 |
commit | 8dbe20898d8e3ae0bada281b793574319ded2bea (patch) | |
tree | 464f5ec5211a727be95e064e08ba038abc68ce6d | |
parent | b10cf7b92e4cd133acf8e117f891f2bbfe759589 (diff) | |
download | PerlNavigator-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.ts | 4 | ||||
-rw-r--r-- | server/src/parser.ts | 44 | ||||
-rw-r--r-- | server/src/symbols.ts | 4 | ||||
-rw-r--r-- | server/src/types.ts | 5 | ||||
-rw-r--r-- | testWorkspace/mainTest.pl | 2 |
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(); |