Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix languge server functions when not Cfn #307

Merged
merged 4 commits into from
Apr 27, 2023
Merged
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
6 changes: 6 additions & 0 deletions server/src/requestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ export namespace PreviewClosed {
"cfn/previewClosed"
);
}

export namespace ResultLimitReachedNotification {
export const type: NotificationType<string> = new NotificationType(
"cfn/resultLimitReached"
);
}
92 changes: 90 additions & 2 deletions server/src/server/handlers/languageHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import { Connection } from "vscode-languageserver";
import {
TextDocumentPositionParams,
DocumentFormattingParams,
DocumentSymbolParams,
DocumentSymbol,
SymbolInformation,
} from "vscode-languageserver-protocol";
import { CompletionList, TextEdit, Hover } from "vscode-languageserver-types";
import { SettingsState } from "../../cfnSettings";
Expand All @@ -31,11 +34,14 @@ import {
} from "yaml-language-server/out/server/src/languageservice/parser/jsonParser07";
import { MarkdownString } from "../../utils/markdownString";
import { LanguageService } from "../../service/cfnLanguageService";
import { ResultLimitReachedNotification } from "../../requestTypes";
import * as path from "path";

// code adopted from https://github.com/redhat-developer/yaml-language-server/blob/main/src/languageserver/handlers/languageHandlers.ts
export class LanguageHandlers extends YamlLanguageHandlers {
private cfnLanguageService: LanguageService;
private cfnSettings: SettingsState;
private cfnConnection: Connection;

pendingLimitExceededWarnings: {
[uri: string]: {
Expand All @@ -51,6 +57,7 @@ export class LanguageHandlers extends YamlLanguageHandlers {
validationHandler: ValidationHandler
) {
super(connection, languageService, cfnSettings, validationHandler);
this.cfnConnection = connection;
this.cfnSettings = cfnSettings;
this.cfnLanguageService = languageService;
}
Expand All @@ -75,14 +82,18 @@ export class LanguageHandlers extends YamlLanguageHandlers {
return Promise.resolve(result);
}

let [node, template] = getNode(textDocument, textDocumentPosition);

if (!template.isValidTemplate && textDocument.lineCount > 4) {
return Promise.resolve(result);
}

const results = await this.cfnLanguageService.doComplete(
textDocument,
textDocumentPosition.position,
false
);

let [node, template] = getNode(textDocument, textDocumentPosition);

function addResources(prefix: string) {
template.resources.forEach((value: TypeInfoImpl, key: string) => {
results.items.push({
Expand Down Expand Up @@ -173,6 +184,53 @@ export class LanguageHandlers extends YamlLanguageHandlers {
return this.cfnLanguageService.doFormat(document, customFormatterSettings);
}

/**
* Called when the code outline in an editor needs to be populated
* Returns a list of symbols that is then shown in the code outline
*/
documentSymbolHandler(
documentSymbolParams: DocumentSymbolParams
): DocumentSymbol[] | SymbolInformation[] {
const document = this.cfnSettings.documents.get(
documentSymbolParams.textDocument.uri
);

if (!document) {
// @ts-ignore
return;
}

let [_, template] = getNode(document, {
textDocument: document,
position: {
line: 0,
character: 0,
},
});

if (!template.isValidTemplate) {
// @ts-ignore
return;
}

const onResultLimitExceeded = this.onCfnResultLimitExceeded(
document.uri,
this.cfnSettings.maxItemsComputed,
"document symbols"
);

const context = {
resultLimit: this.cfnSettings.maxItemsComputed,
onResultLimitExceeded,
};

if (this.cfnSettings.hierarchicalDocumentSymbolSupport) {
return this.cfnLanguageService.findDocumentSymbols2(document, context);
} else {
return this.cfnLanguageService.findDocumentSymbols(document, context);
}
}

/**
* Called when the user hovers with their mouse over a keyword
* Returns an informational tooltip
Expand Down Expand Up @@ -240,4 +298,34 @@ export class LanguageHandlers extends YamlLanguageHandlers {

return hover;
}

private onCfnResultLimitExceeded(
uri: string,
resultLimit: number,
name: string
) {
return () => {
let warning = this.pendingLimitExceededWarnings[uri];
if (warning) {
if (!warning.timeout) {
// already shown
return;
}
warning.features[name] = name;
warning.timeout.refresh();
} else {
warning = { features: { [name]: name } };
warning.timeout = setTimeout(() => {
this.cfnConnection.sendNotification(
ResultLimitReachedNotification.type,
`${path.basename(uri)}: For performance reasons, ${Object.keys(
warning.features
).join(" and ")} have been limited to ${resultLimit} items.`
);
warning.timeout = undefined;
}, 2000);
this.pendingLimitExceededWarnings[uri] = warning;
}
};
}
}