Skip to content

Commit

Permalink
Adding TODOs and linting
Browse files Browse the repository at this point in the history
  • Loading branch information
AnHeuermann committed May 23, 2024
1 parent 85bbe3f commit 24f92c8
Show file tree
Hide file tree
Showing 11 changed files with 14 additions and 172 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ module.exports = {
],
rules: {
'semi': [2, "always"],
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': ["warn"],
'@typescript-eslint/no-unused-expressions': ["warn"],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-non-null-assertion': 0,
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
- name: Build package
run: npm run esbuild

- name: ESLint
run: npm run lint

- name: Test language server
run: npm run test:server

Expand Down
1 change: 0 additions & 1 deletion client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import {
TransportKind,
} from 'vscode-languageclient/node';
import { getFileExtension, getLanguage } from './getLanguage';
import { fstat } from 'fs';

let client: LanguageClient;

Expand Down
22 changes: 0 additions & 22 deletions client/src/test/symbolinformation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,9 @@ async function testSymbolInformation(
docUri,
);

//printDocumentSymbols(actualSymbolInformation);
assertDocumentSymbolsEqual(expectedDocumentSymbols, actualSymbolInformation);
}

function printDocumentSymbols(documentSymbols: vscode.DocumentSymbol[]) {
documentSymbols.forEach((symbol, index) => {
console.log(`Document Symbol ${index + 1}:`);
console.log(`Name: ${symbol.name}`);
console.log(`Kind: ${vscode.SymbolKind[symbol.kind]}`);
console.log(
`Range: ${symbol.range.start.line}:${symbol.range.start.character}, ${symbol.range.end.line}:${symbol.range.end.character}`,
);
console.log(
`SelectionRange: ${symbol.selectionRange.start.line}:${symbol.selectionRange.start.character}, ${symbol.selectionRange.end.line}:${symbol.selectionRange.end.character}`,
);
console.log('Children:');

if (symbol.children && symbol.children.length > 0) {
printDocumentSymbols(symbol.children);
}

console.log('---');
});
}

function assertDocumentSymbolsEqual(
expected: vscode.DocumentSymbol[],
actual: vscode.DocumentSymbol[],
Expand Down
4 changes: 1 addition & 3 deletions server/src/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@

import * as LSP from 'vscode-languageserver/node';
import { TextDocument } from 'vscode-languageserver-textdocument';
import * as fs from 'fs';
import Parser = require('web-tree-sitter');

import { getAllDeclarationsInTree } from './util/declarations';
import { logger } from './util/logger';
import { log } from 'console';

type AnalyzedDocument = {
document: TextDocument;
Expand Down Expand Up @@ -120,7 +118,7 @@ export default class Analyzer {

// Find all declarations matching identifier.
for (const availableUri of Object.keys(this.#uriToAnalyzedDocument)) {
// TODO: Filter reachable uri, e.g. because of an inclue
// TODO: Filter reachable uri, e.g. because of an include
const decl = this.#uriToAnalyzedDocument[availableUri]?.declarations;
if (decl) {
for (const d of decl) {
Expand Down
79 changes: 2 additions & 77 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,11 @@
* ----------------------------------------------------------------------------
*/

import * as path from 'node:path';
import * as LSP from 'vscode-languageserver/node';
import { TextDocument } from 'vscode-languageserver-textdocument';

import { initializeParser } from './parser';
import Analyzer from './analyzer';
import { uniqueBasedOnHash } from './util/array';
import { extractHoverInformation } from './util/hoverUtil';
import { logger, setLogConnection, setLogLevel } from './util/logger';

Expand Down Expand Up @@ -142,34 +140,7 @@ export class ModelicaServer {
}

private async analyzeDocument(document: TextDocument) {
const diagnostics = this.#analyzer.analyze(document);
}

private getCommentForSymbol({
currentUri,
symbol,
}: {
symbol: LSP.SymbolInformation
currentUri: string
}): string {

logger.debug(`getDocumentationForSymbol: symbol=${symbol.name} uri=${symbol.location.uri}`);

const symbolUri = symbol.location.uri;
const symbolStartLine = symbol.location.range.start.line;

const commentAboveSymbol = this.#analyzer.commentsAbove(symbolUri, symbolStartLine);
const commentAbove = commentAboveSymbol ? `\n\n${commentAboveSymbol}` : '';
const hoverHeader = `${symbolKindToDescription(symbol.kind)}: **${symbol.name}**`;
const symbolLocation =
symbolUri !== currentUri
? `in ${path.relative(path.dirname(currentUri), symbolUri)}`
: `on line ${symbolStartLine + 1}`;

// TODO: An improvement could be to add show the symbol definition in the hover instead
// of the defined location – similar to how VSCode works for languages like TypeScript.

return `\n${commentAbove}`;
this.#analyzer.analyze(document);
}

// ==============================
Expand Down Expand Up @@ -216,6 +187,7 @@ export class ModelicaServer {
return null;
}

// TODO: Get node defining symbol and extract hover information of that one.
const hoverInfo = extractHoverInformation(node);
if (hoverInfo == null) {
return null;
Expand All @@ -233,53 +205,6 @@ export class ModelicaServer {
}
}

/**
* Deduplicate symbols by prioritizing the current file.
*/
function deduplicateSymbols({
symbols,
currentUri,
}: {
symbols: LSP.SymbolInformation[]
currentUri: string
}) {
const isCurrentFile = ({ location: { uri } }: LSP.SymbolInformation) =>
uri === currentUri;

const getSymbolId = ({ name, kind }: LSP.SymbolInformation) => `${name}${kind}`;

const symbolsCurrentFile = symbols.filter((s) => isCurrentFile(s));

const symbolsOtherFiles = symbols
.filter((s) => !isCurrentFile(s))
// Remove identical symbols matching current file
.filter(
(symbolOtherFiles) =>
!symbolsCurrentFile.some(
(symbolCurrentFile) =>
getSymbolId(symbolCurrentFile) === getSymbolId(symbolOtherFiles),
),
);

// NOTE: it might be that uniqueBasedOnHash is not needed anymore
return uniqueBasedOnHash([...symbolsCurrentFile, ...symbolsOtherFiles], getSymbolId);
}

function symbolKindToDescription(kind: LSP.SymbolKind): string {
switch (kind) {
case LSP.SymbolKind.Class:
return 'Class';
case LSP.SymbolKind.Function:
return 'Function';
case LSP.SymbolKind.Package:
return 'Package';
case LSP.SymbolKind.TypeParameter:
return 'Type';
default:
return 'Modelica symbol';
}
}

// Create a connection for the server, using Node's IPC as a transport.
// Also include all preview / proposed LSP features.
const connection = LSP.createConnection(LSP.ProposedFeatures.all);
Expand Down
4 changes: 1 addition & 3 deletions server/src/test/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@
*
*/

import * as Mocha from 'mocha';
import * as assert from 'assert';
import * as Parser from 'web-tree-sitter';

import { initializeParser } from '../parser';

Expand All @@ -51,7 +49,7 @@ const parsedModelicaTestString =

describe('Modelica tree-sitter parser', () => {
it('Initialize parser', async () => {
const parser = await initializeParser();
await initializeParser();
});

it('Parse string', async () => {
Expand Down
24 changes: 0 additions & 24 deletions server/src/util/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,3 @@ export function flattenArray<T>(nestedArray: T[][]): T[] {
export function uniq<A>(a: A[]): A[] {
return Array.from(new Set(a));
}

/**
* Removed all duplicates from the list based on the hash function.
* First element matching the hash function wins.
*/
export function uniqueBasedOnHash<A extends Record<string, any>>(
list: A[],
elementToHash: (a: A) => string,
__result: A[] = [],
): A[] {
const result: typeof list = [];
const hashSet = new Set<string>();

list.forEach((element) => {
const hash = elementToHash(element);
if (hashSet.has(hash)) {
return;
}
hashSet.add(hash);
result.push(element);
});

return result;
}
5 changes: 0 additions & 5 deletions server/src/util/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,17 @@ import * as LSP from 'vscode-languageserver/node';
import * as Parser from 'web-tree-sitter';

import * as TreeSitterUtil from './tree-sitter';
import { logger } from './logger';

const isEmpty = (data: string): boolean => typeof data === 'string' && data.trim().length == 0;

export type GlobalDeclarations = { [word: string]: LSP.SymbolInformation };
export type Declarations = { [word: string]: LSP.SymbolInformation[] };

const GLOBAL_DECLARATION_LEAF_NODE_TYPES = new Set(['if_statement', 'function_definition']);

export function getLocalDeclarations({
node,
rootNode,
uri,
}: {
node: Parser.SyntaxNode | null
rootNode: Parser.SyntaxNode
uri: string
}): Declarations {
const declarations: Declarations = {};
Expand Down
39 changes: 5 additions & 34 deletions server/src/util/hoverUtil.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { SyntaxNode } from 'web-tree-sitter';
import * as TreeSitterUtil from './tree-sitter';
import * as LSP from 'vscode-languageserver';
import { logger } from './logger';

/**
Expand All @@ -9,6 +8,10 @@ import { logger } from './logger';
* Documentation and information for class description, inputs, outputs and
* parameters.
*
* TODO: Modify this function to accept class_definition and
* component_declaration and so on.
* TODO: Use querries instead of checking children.
*
* @param node Syntax Node.
*
* @returns Hover content or null if no information available.
Expand All @@ -22,7 +25,7 @@ export function extractHoverInformation(node: SyntaxNode): string | null {
}

// Check if node is the first IDENT child of the class_definition, indicating it's the class name.
const isClassName = classDefNode.namedChildren.some((child, _) =>
const isClassName = classDefNode.namedChildren.some((child) =>
child.type === 'long_class_specifier' &&
child.firstChild?.type === 'IDENT' &&
child.firstChild?.text === node.text);
Expand Down Expand Up @@ -168,35 +171,3 @@ function extractComponentInformation(
parameterOutputsInfo: parameterOutputsString,
};
}

function extractParameterInformation(classDefNode: SyntaxNode): string {
const parametersInfo: string[] = [];

TreeSitterUtil.forEach(classDefNode, (node) => {

if (node.type === 'component_clause' && node.text.includes('parameter')) {

const typeSpecifierNode = node.childForFieldName('typeSpecifier');
logger.debug(`Type specifier node: ${typeSpecifierNode}`);
const typeSpecifier = typeSpecifierNode ? typeSpecifierNode.text : "Unknown Type";

const componentDeclarationNode = node.childForFieldName('componentDeclarations');

const declarationNode = componentDeclarationNode?.firstChild?.childForFieldName('declaration');
logger.debug(`Declaration node: ${declarationNode}`);
const identifier = declarationNode ? declarationNode.text : "Unknown Identifier";

// Extracting description from description_string node
const descriptionNode = componentDeclarationNode?.firstChild?.childForFieldName('descriptionString');
const description = descriptionNode ? descriptionNode.text : '';

parametersInfo.push(`${typeSpecifier} ${identifier} ${description}\n`);
}
return true;
});

if (parametersInfo.length > 0) {
return "\n## Parameters:\n" + parametersInfo.join('\n');
}
return '';
}
2 changes: 0 additions & 2 deletions server/src/util/tree-sitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@
import * as LSP from 'vscode-languageserver/node';
import { SyntaxNode } from 'web-tree-sitter';

import { logger } from './logger';

/**
* Recursively iterate over all nodes in a tree.
*
Expand Down

0 comments on commit 24f92c8

Please sign in to comment.