Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions server/src/core/codelens-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* @fileoverview Handles all CodeLens logic for Apache Dispatcher Config files.
* @author Darian Benam <[email protected]>
*/

import { ApacheDispatcherConfigToken } from "@language-server/core/tree-sitter";
import { removeOuterQuotes } from "@language-server/utils/string";
import { CodeLens, Command, Range } from "vscode-languageserver";
import Parser = require("web-tree-sitter");

function containsEnvironmentVariable(value: string): boolean {
return /\$\{.*?\}/.test(value);
}

export function getCodeLensDefinitions(syntaxTree: Parser.Tree | undefined): CodeLens[] {
if (syntaxTree === undefined) {
return [];
}

const codeLensDefinitions: CodeLens[] = [];
const syntaxNodeStack: Parser.SyntaxNode[] = [ syntaxTree.rootNode ];

while (syntaxNodeStack.length > 0) {
const syntaxNode: Parser.SyntaxNode | undefined = syntaxNodeStack.pop();

if (syntaxNode === undefined || syntaxNode.hasError()) {
continue;
}

const syntaxNodeValue: string = removeOuterQuotes(syntaxNode.text);

if (
syntaxNode.type === ApacheDispatcherConfigToken.String &&
containsEnvironmentVariable(syntaxNodeValue)
) {
const range: Range = {
start: {
line: syntaxNode.startPosition.row,
character: syntaxNode.startPosition.column
},
end: {
line: syntaxNode.endPosition.row,
character: syntaxNode.endPosition.column
}
};

// TODO: Look into creating a lookup table for environment variables under the /conf.d/variables folder
codeLensDefinitions.push({
range: range,
command: Command.create(`"${syntaxNodeValue}" resolves to ""`, "")
});
}

for (const childNode of syntaxNode.children) {
syntaxNodeStack.push(childNode);
}
}

return codeLensDefinitions;
}
17 changes: 1 addition & 16 deletions server/src/core/definition-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { INCLUDE_FUNCTION_NAME } from "@language-server/constants/function";
import { DocumentParserTreeManager } from "@language-server/core/document-parser-tree-manager";
import { ApacheDispatcherConfigToken, getCurrentSyntaxNode } from "@language-server/core/tree-sitter";
import { FileExistenceContext, getFileExistenceContext } from "@language-server/utils/file-system";
import { removeOuterQuotes } from "@language-server/utils/string";
import {
DefinitionLink,
DefinitionParams,
Expand All @@ -19,22 +20,6 @@ import Parser = require("web-tree-sitter");
const START_POSITION: Position = Position.create(0, 0);
const START_POSITION_RANGE: Range = Range.create(START_POSITION, START_POSITION);

function isSingleQuoteString(text: string): boolean {
return text.startsWith("'") && text.endsWith("'");
}

function isDoubleQuoteString(text: string): boolean {
return text.startsWith("\"") && text.endsWith("\"");
}

function removeOuterQuotes(text: string): string {
if (isSingleQuoteString(text) || isDoubleQuoteString(text)) {
return text.substring(1, text.length - 1);
}

return text;
}

export async function getDefinition(
documentParserTreeManager: DocumentParserTreeManager,
definitionParams: DefinitionParams
Expand Down
8 changes: 6 additions & 2 deletions server/src/core/document-parser-tree-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
* @author Darian Benam <[email protected]>
*/

import { getCodeLensDefinitions } from "@language-server/core/codelens-provider";
import {
ApacheDispatcherConfigToken,
loadApacheDispatcherConfigTreeSitterLanguage,
tokenizeTextDocument
} from "@language-server/core/tree-sitter";
import { DocumentSymbol, SymbolKind, TextDocuments } from "vscode-languageserver";
import { CodeLens, DocumentSymbol, SymbolKind, TextDocuments } from "vscode-languageserver";
import { Range, TextDocument } from "vscode-languageserver-textdocument";
import Parser = require("web-tree-sitter");

Expand Down Expand Up @@ -98,7 +99,6 @@ export class DocumentParserTreeManager {
};
}


private getApacheDispatcherConfigTokenSymbolKind(tokenType: ApacheDispatcherConfigToken): SymbolKind {
switch (tokenType) {
case ApacheDispatcherConfigToken.Function:
Expand Down Expand Up @@ -194,6 +194,10 @@ export class DocumentParserTreeManager {
return rootSymbols;
}

public getDocumentCodeLensDefinitions(documentUri: string): CodeLens[] {
return getCodeLensDefinitions(this.documentParseTree.get(documentUri))
}

public updateParseTree(document: TextDocument): void {
if (this.treeSitterParser === undefined) {
throw new Error("Tree-sitter parser has not been initialized!");
Expand Down
19 changes: 19 additions & 0 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import * as path from "path";
import { TextDocument } from "vscode-languageserver-textdocument";
import {
ClientCapabilities,
CodeLens,
CodeLensParams,
CompletionItem,
Connection,
DefinitionLink,
Expand Down Expand Up @@ -50,6 +52,9 @@ CONNECTION.onInitialize(async function(initializeParams: InitializeParams): Prom

const result: InitializeResult = {
capabilities: {
codeLensProvider: {
resolveProvider: true
},
completionProvider: {
triggerCharacters: AUTOCOMPLETION_TRIGGER_CHARACTERS
},
Expand Down Expand Up @@ -85,6 +90,20 @@ CONNECTION.onInitialized(async function(): Promise<void> {
console.info("Language server initialized.");
});

CONNECTION.onCodeLens(async function(params: CodeLensParams): Promise<CodeLens[]> {
if (documentParserTreeManager === undefined) {
await waitForDocumentParserTreeManagerInitialization(documentParserTreeManager);
}

const document: TextDocument | undefined = DOCUMENT_MANAGER.get(params.textDocument.uri);

if (document === undefined) {
return [];
}

return documentParserTreeManager.getDocumentCodeLensDefinitions(document.uri);
});

CONNECTION.onCompletion(
async (textDocumentPositionParams: TextDocumentPositionParams): Promise<CompletionItem[]> => {
return await handleAutoCompletion(
Expand Down
20 changes: 20 additions & 0 deletions server/src/utils/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @fileoverview Miscellaneous utility functions for dealing with strings.
* @author Darian Benam <[email protected]>
*/

function isSingleQuoteString(text: string): boolean {
return text.startsWith("'") && text.endsWith("'");
}

function isDoubleQuoteString(text: string): boolean {
return text.startsWith("\"") && text.endsWith("\"");
}

export function removeOuterQuotes(text: string): string {
if (isSingleQuoteString(text) || isDoubleQuoteString(text)) {
return text.substring(1, text.length - 1);
}

return text;
}
Loading