Skip to content

Commit

Permalink
Fix bug in languageserver hover provider (#649)
Browse files Browse the repository at this point in the history
* Fix bug in languageserver hover provider

* Better separation of hovers.

* fix ts error
  • Loading branch information
TwitchBronBron committed Jul 22, 2022
1 parent 9a08fc2 commit 704e10e
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 34 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 26 additions & 25 deletions src/LanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1003,32 +1003,33 @@ export class LanguageServer {

const srcPath = util.uriToPath(params.textDocument.uri);
let projects = this.getProjects();
let hovers = projects.map((x) => x.builder.program.getHover(srcPath, params.position)).flat();
hovers = [hovers[0], hovers[0], hovers[0]];

//eliminate duplicate hover text, and merge all hovers together into a single newline-separated string
const hoverText = [
...hovers
//remove undefined hovers
let hovers = projects
//get hovers from all projects
.map((x) => x.builder.program.getHover(srcPath, params.position))
//flatten to a single list
.flat();

const contents = [
...(hovers ?? [])
//pull all hover contents out into a flag array of strings
.map(x => {
return Array.isArray(x?.contents) ? x?.contents : [x?.contents];
}).flat()
//remove nulls
.filter(x => !!x)
//dedupe and merge inner hovers
.reduce((set, hover) => {
const hoverContentArray = Array.isArray(hover.contents) ? hover.contents : [hover.contents];
const hoverText = hoverContentArray.map(x => {
return typeof x === 'string' ? x : x?.value;
}).join('\n');
return set.add(hoverText);
}, new Set<string>()).values()
//merge outer hovers
].join('\n');

let hover: Hover = {
//use the range from the first hover
range: hovers[0]?.range,
//merge all the hovers into a single string, separated by newlines
contents: hoverText
};
return hover;
//dedupe hovers across all projects
.reduce((set, content) => set.add(content), new Set<string>()).values()
];

if (contents.length > 0) {
let hover: Hover = {
//use the range from the first hover
range: hovers[0]?.range,
//the contents of all hovers
contents: contents
};
return hover;
}
}

@AddStackToErrorMessage
Expand Down
9 changes: 6 additions & 3 deletions src/Program.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as assert from 'assert';
import * as fsExtra from 'fs-extra';
import * as path from 'path';
import type { CodeAction, CompletionItem, Position, Range, SignatureInformation, Location, Hover } from 'vscode-languageserver';
import type { CodeAction, CompletionItem, Position, Range, SignatureInformation, Location } from 'vscode-languageserver';
import { CompletionItemKind } from 'vscode-languageserver';
import type { BsConfig } from './BsConfig';
import { Scope } from './Scope';
import { DiagnosticMessages } from './DiagnosticMessages';
import { BrsFile } from './files/BrsFile';
import { XmlFile } from './files/XmlFile';
import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken, AfterFileTranspileEvent, FileLink, ProvideHoverEvent, ProvideCompletionsEvent } from './interfaces';
import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken, AfterFileTranspileEvent, FileLink, ProvideHoverEvent, ProvideCompletionsEvent, Hover } from './interfaces';
import { standardizePath as s, util } from './util';
import { XmlScope } from './XmlScope';
import { DiagnosticFilterer } from './DiagnosticFilterer';
Expand Down Expand Up @@ -901,6 +901,7 @@ export class Program {
*/
public getHover(srcPath: string, position: Position): Hover[] {
let file = this.getFile(srcPath);
let result: Hover[];
if (file) {
const event = {
program: this,
Expand All @@ -912,8 +913,10 @@ export class Program {
this.plugins.emit('beforeProvideHover', event);
this.plugins.emit('provideHover', event);
this.plugins.emit('afterProvideHover', event);
return event.hovers;
result = event.hovers;
}

return result ?? [];
}

/**
Expand Down
3 changes: 1 addition & 2 deletions src/bscPlugin/hover/HoverProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { SourceNode } from 'source-map';
import type { Hover } from 'vscode-languageserver-types';
import { isBrsFile, isFunctionType, isXmlFile } from '../../astUtils/reflection';
import type { BrsFile } from '../../files/BrsFile';
import type { XmlFile } from '../../files/XmlFile';
import type { ProvideHoverEvent } from '../../interfaces';
import type { Hover, ProvideHoverEvent } from '../../interfaces';
import type { Token } from '../../lexer/Token';
import { TokenKind } from '../../lexer/TokenKind';
import { BrsTranspileState } from '../../parser/BrsTranspileState';
Expand Down
17 changes: 16 additions & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Range, Diagnostic, CodeAction, SemanticTokenTypes, SemanticTokenModifiers, Position, Hover, CompletionItem } from 'vscode-languageserver';
import type { Range, Diagnostic, CodeAction, SemanticTokenTypes, SemanticTokenModifiers, Position, CompletionItem } from 'vscode-languageserver';
import type { Scope } from './Scope';
import type { BrsFile } from './files/BrsFile';
import type { XmlFile } from './files/XmlFile';
Expand Down Expand Up @@ -284,6 +284,21 @@ export interface ProvideHoverEvent {
scopes: Scope[];
hovers: Hover[];
}
export interface Hover {
/**
* The contents of the hover, written in markdown. If you want to display code in the hover, use code blocks, like this:
* ```text
* ```brighterscript
* some = "code" + "here"
* ```
* ```
*/
contents: string | string[];
/**
* An optional range
*/
range?: Range;
}
export type BeforeProvideHoverEvent = ProvideHoverEvent;
export type AfterProvideHoverEvent = ProvideHoverEvent;

Expand Down

0 comments on commit 704e10e

Please sign in to comment.