diff options
author | bscan <10503608+bscan@users.noreply.github.com> | 2023-10-29 18:45:17 -0400 |
---|---|---|
committer | bscan <10503608+bscan@users.noreply.github.com> | 2023-10-29 18:45:17 -0400 |
commit | e28bf30c15f49f8ecbac61fd642d071023b8b6f8 (patch) | |
tree | a6df58d5af42c3e44b5fe268235cbf58da37a1ba | |
parent | f27a20640166a964558994857bfba5713db4f50a (diff) | |
download | PerlNavigator-e28bf30c15f49f8ecbac61fd642d071023b8b6f8.zip |
Adding ability to look up pod in .pod files, as well as find pod files by module name. Also, fixing minor Moose related regex
-rw-r--r-- | server/src/completion.ts | 4 | ||||
-rw-r--r-- | server/src/hover.ts | 2 | ||||
-rw-r--r-- | server/src/navigation.ts | 11 | ||||
-rw-r--r-- | server/src/perl/Inquisitor.pm | 2 | ||||
-rw-r--r-- | server/src/pod.ts | 106 | ||||
-rw-r--r-- | server/src/server.ts | 5 | ||||
-rw-r--r-- | server/src/utils.ts | 11 |
7 files changed, 101 insertions, 40 deletions
diff --git a/server/src/completion.ts b/server/src/completion.ts index fa99c41..dded519 100644 --- a/server/src/completion.ts +++ b/server/src/completion.ts @@ -41,8 +41,8 @@ export function getCompletions( } -export async function getCompletionDoc(elem: PerlElem, perlDoc: PerlDocument): Promise<string | undefined> { - let docs = await getPod(elem, perlDoc); +export async function getCompletionDoc(elem: PerlElem, perlDoc: PerlDocument, modMap: Map<string, string>): Promise<string | undefined> { + let docs = await getPod(elem, perlDoc, modMap); return docs; } diff --git a/server/src/hover.ts b/server/src/hover.ts index 591d320..3509342 100644 --- a/server/src/hover.ts +++ b/server/src/hover.ts @@ -30,7 +30,7 @@ export async function getHover(params: TextDocumentPositionParams, perlDoc: Perl let merged = title; - let docs = await getPod(elem, perlDoc); + let docs = await getPod(elem, perlDoc, modMap); if(docs){ merged += "\n" + docs; diff --git a/server/src/navigation.ts b/server/src/navigation.ts index 0bded54..688d615 100644 --- a/server/src/navigation.ts +++ b/server/src/navigation.ts @@ -3,7 +3,7 @@ import { TextDocument } from "vscode-languageserver-textdocument"; import { PerlDocument, PerlElem, NavigatorSettings, ElemSource, ParseType } from "./types"; import Uri from "vscode-uri"; import { realpathSync, existsSync, realpath, promises } from "fs"; -import { getIncPaths, async_execFile, getSymbol, lookupSymbol, nLog } from "./utils"; +import { getIncPaths, async_execFile, getSymbol, lookupSymbol, nLog, isFile } from "./utils"; import { dirname, join } from "path"; import { getPerlAssetsPath } from "./assets"; import { refineElement } from "./refinement"; @@ -53,15 +53,6 @@ export async function getDefinition(params: DefinitionParams, perlDoc: PerlDocum return locationsFound; } -async function isFile(file: string): Promise<boolean> { - try { - const stats = await promises.stat(file); - return stats.isFile(); - } catch (err) { - // File or directory doesn't exist - return false; - } -} async function resolveElemForNav(perlDoc: PerlDocument, elem: PerlElem, symbol: string): Promise<PerlElem | undefined> { let refined = await refineElement(elem, perlDoc); diff --git a/server/src/perl/Inquisitor.pm b/server/src/perl/Inquisitor.pm index af09bd9..027dffb 100644 --- a/server/src/perl/Inquisitor.pm +++ b/server/src/perl/Inquisitor.pm @@ -167,7 +167,7 @@ sub resolve_file { } # Moose (but not Moo) attributes return this for a file. - if ($file =~ /^accessor [\w:]+ \(defined at ([\w\\\/\.\s]+) line (\d+)\)$/){ + if ($file =~ /^accessor [\w:]+ \(defined at (.+) line (\d+)\)$/){ $file = $1; $line = $2; $subType = 'd'; diff --git a/server/src/pod.ts b/server/src/pod.ts index 8e0efdb..672c9fb 100644 --- a/server/src/pod.ts +++ b/server/src/pod.ts @@ -1,11 +1,13 @@ import fs = require("fs"); import { PerlDocument, PerlElem, PerlSymbolKind } from "./types"; import Uri from "vscode-uri"; +import { isFile } from "./utils"; -export async function getPod(elem: PerlElem, perlDoc: PerlDocument): Promise<string | undefined> { +export async function getPod(elem: PerlElem, perlDoc: PerlDocument, modMap: Map<string, string>): Promise<string | undefined> { // File may not exists. Return nothing if it doesn't - const absolutePath = resolvePathForDoc(elem, perlDoc); + const absolutePath = await resolvePathForDoc(elem, perlDoc, modMap); + if(!absolutePath) return; try { @@ -64,41 +66,91 @@ export async function getPod(elem: PerlElem, perlDoc: PerlDocument): Promise<str } } - if(meaningFullContent){ + if(meaningFullContent && podBuffer != ""){ podContent += podBuffer; podBuffer = ""; } } - + const markDown = convertPODToMarkdown(podContent); return markDown; } -const resolvePathForDoc = (elem: PerlElem, perlDoc: PerlDocument): string | undefined => { + +async function resolvePathForDoc(elem: PerlElem, perlDoc: PerlDocument, modMap: Map<string, string>): Promise<string | undefined> { let absolutePath = Uri.parse(elem.uri).fsPath; - const badFile = (c: string) => /\w+\.c$/.test(c); - - if(badFile(absolutePath)){ - // Lookup by package or module? - if (elem.package) { - const elemResolved = perlDoc.elems.get(elem.package); - if (elemResolved) { - for (let potentialElem of elemResolved) { - const potentialPath = Uri.parse(potentialElem.uri).fsPath; - if (potentialPath.length > 1 && !badFile(potentialPath)) { - absolutePath = potentialPath; - break; - } + const foundPath = await fsPathOrAlt(absolutePath); + if(foundPath){ + return foundPath; + } + + if (elem.package) { + let elemResolved = perlDoc.elems.get(elem.package); + + if(!elemResolved){ + + // Looking up a module by the package name is only convention, but helps for things like POSIX + const modUri = modMap.get(elem.package); + if(modUri){ + let modPath = await fsPathOrAlt(Uri.parse(modUri).fsPath); + if(modPath){ + return modPath; } } - } - if(badFile(absolutePath)){ return; } + + + for (let potentialElem of elemResolved) { + const potentialPath = Uri.parse(potentialElem.uri).fsPath; + const foundPackPath = await fsPathOrAlt(potentialPath); + if (foundPackPath) { + return foundPackPath; + } + } + } + if(await badFile(absolutePath)){ + return; + } + +} + +async function fsPathOrAlt(fsPath: string | undefined): Promise<string | undefined>{ + + if(!fsPath){ + return; + } + + if(/\.pm$/.test(fsPath)){ + let podPath = fsPath.replace(/\.pm$/, ".pod"); + if(!await badFile(podPath)){ + return podPath; + } } - return absolutePath; + if(!await badFile(fsPath)){ + return fsPath; + } + return; + +} + +async function badFile(fsPath: string): Promise<boolean> { + + if (!fsPath || fsPath.length <= 1) { + return true; + } + + if( /\w+\.c$/.test(fsPath) ){ + return true; + } + + if(!(await isFile(fsPath))){ + return true; + } + + return false; } type ConversionState = { @@ -147,9 +199,9 @@ const convertPODToMarkdown = (pod: string): string => { else if (line.startsWith("=head")) { const output = processHeadings(line); - if(output != "\n## NAME\n" && /\w/.test(finalMarkdown)){ + if(/\w/.test(finalMarkdown) || !/^\n##+ NAME\n$/.test(output)){ // I find it a waste of space to include the headline "NAME". We're short on space in the hover - finalMarkdown += processHeadings(line); + finalMarkdown += output; } } // List markers and items @@ -345,9 +397,13 @@ const processInlineElements = (line: string): string => { // Handle italics (I<italic>) line = line.replace(/I<([^>]+)>/g, "*$1*"); + line = line.replace(/I<< (.+?) >>>/g, "*$1*"); + + // Handle links (L<name>), URLS auto-link in vscode's markdown + line = line.replace(/L<(http[^>]+)>/g, " $1 "); - // Handle links (L<name>), we'll just keep the name for now - line = line.replace(/L<([^>]+)>/g, "[$1]"); + line = line.replace(/L<([^>]+)>/g, "`$1`"); + line = line.replace(/L<< (.*?) >>/g, "`$1`"); // Handle non-breaking spaces (S<text>) line = line.replace(/S<([^>]+)>/g, "$1"); diff --git a/server/src/server.ts b/server/src/server.ts index eabe144..943516e 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -348,7 +348,10 @@ connection.onCompletionResolve(async (item: CompletionItem): Promise<CompletionI let perlDoc = navSymbols.get(item.data?.docUri); if (!perlDoc) return item; - const docs = await getCompletionDoc(perlElem, perlDoc); + let mods = availableMods.get("default"); + if (!mods) mods = new Map(); + + const docs = await getCompletionDoc(perlElem, perlDoc, mods); if (docs?.match(/\w/)) { item.documentation = { kind: "markdown", value: docs };; } diff --git a/server/src/utils.ts b/server/src/utils.ts index 91ed4fa..61d5509 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -5,6 +5,7 @@ import { promisify } from "util"; import { TextDocument, Position } from "vscode-languageserver-textdocument"; import { PerlDocument, PerlElem, NavigatorSettings, PerlSymbolKind, ElemSource } from "./types"; import * as path from "path"; +import { promises } from "fs"; export const async_execFile = promisify(execFile); @@ -258,3 +259,13 @@ export function getPerlimportsProfile(settings: NavigatorSettings): string[] { } return profileCmd; } + +export async function isFile(file: string): Promise<boolean> { + try { + const stats = await promises.stat(file); + return stats.isFile(); + } catch (err) { + // File or directory doesn't exist + return false; + } +}
\ No newline at end of file |