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

Only support JSON snippets for empty files #1326

Merged
merged 2 commits into from
Jul 16, 2021
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
4 changes: 2 additions & 2 deletions assets/armsnippets.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
/*
Known contexts (see KnownContexts.ts)

empty-document
empty-document (also works for plain JSON files)
parameter-definitions
parameter-values
userfunc-parameter-definitions
resource-body

If a location in a template document does not match ones of the above, then it will
If a location in a template document does not match one of the above, then it will
be set to the name of the property containing the current array or object (e.g. "resources" or "outputs"),
if any.
*/
Expand Down
80 changes: 0 additions & 80 deletions assets/jsonsnippets.jsonc

This file was deleted.

10 changes: 0 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,6 @@
"path": "dist/grammars/arm-expression-string.tmLanguage.json"
}
],
"snippets": [
{
"language": "json",
"path": "./assets/jsonsnippets.jsonc"
},
{
"language": "jsonc",
"path": "./assets/jsonsnippets.jsonc"
}
],
"configuration": {
"type": "object",
"title": "Azure Resource Manager Tools",
Expand Down
111 changes: 78 additions & 33 deletions src/AzureRMTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ import { DeploymentTemplateDoc } from "./documents/templates/DeploymentTemplateD
import { ExtractItem } from './documents/templates/ExtractItem';
import { getNormalizedDocumentKey } from './documents/templates/getNormalizedDocumentKey';
import { gotoResources } from './documents/templates/gotoResources';
import { IJsonDocument } from './documents/templates/IJsonDocument';
import { getItemTypeQuickPicks, InsertItem } from "./documents/templates/insertItem";
import { assignTemplateGraphToDeploymentTemplate, INotifyTemplateGraphArgs, openLinkedTemplateFileCommand, tryLoadNonLocalLinkedFile } from './documents/templates/linkedTemplates/linkedTemplates';
import { allSchemas, getPreferredSchema } from './documents/templates/schemas';
import { getQuickPickItems, sortTemplate } from "./documents/templates/sortTemplate";
import { mightBeDeploymentParameters, mightBeDeploymentTemplate, setLangIdToArm, templateDocumentSelector, templateOrParameterDocumentSelector } from "./documents/templates/supported";
import { TemplateSectionType } from "./documents/templates/TemplateSectionType";
import { UnsupportedJsonDocument } from './documents/UnsupportedJsonDocument';
import { ext } from "./extensionVariables";
import { assert } from './fixed_assert';
import { IProvideOpenedDocuments } from './IProvideOpenedDocuments';
Expand All @@ -40,6 +42,8 @@ import { ReferenceList } from "./language/ReferenceList";
import { Span } from "./language/Span";
import { getAvailableResourceTypesAndVersions } from './languageclient/getAvailableResourceTypesAndVersions';
import { notifyTemplateGraphAvailable, startArmLanguageServerInBackground, waitForLanguageServerAvailable } from "./languageclient/startArmLanguageServer";
import { InsertionContext } from './snippets/InsertionContext';
import { KnownContexts } from './snippets/KnownContexts';
import { showInsertionContext } from "./snippets/showInsertionContext";
import { SnippetManager } from "./snippets/SnippetManager";
import { survey } from "./survey";
Expand All @@ -57,6 +61,7 @@ import { parseUri } from './util/uri';
import { IncorrectArgumentsCountIssue } from "./visitors/IncorrectArgumentsCountIssue";
import { UnrecognizedBuiltinFunctionIssue } from "./visitors/UnrecognizedFunctionIssues";
import { IAddMissingParametersArgs, IGotoParameterValueArgs, IGotoResourcesArgs } from "./vscodeIntegration/commandArguments";
import { Item } from './vscodeIntegration/Completion';
import { ConsoleOutputChannelWrapper } from "./vscodeIntegration/ConsoleOutputChannelWrapper";
import { IHoverInfo } from './vscodeIntegration/IHoverInfo';
import { RenameCodeActionProvider } from "./vscodeIntegration/RenameCodeActionProvider";
Expand Down Expand Up @@ -333,6 +338,34 @@ export class AzureRMTools implements IProvideOpenedDocuments {
this._diagnosticsCollection = vscode.languages.createDiagnosticCollection("azurerm-tools-expressions");
context.subscriptions.push(this._diagnosticsCollection);

// Hook up completion provider immediately because it also handles unsupported JSON files (for non-template JSON files)
const completionProvider: vscode.CompletionItemProvider = {
provideCompletionItems: async (
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
ctx: vscode.CompletionContext
): Promise<vscode.CompletionList | undefined> => {
return await this.onProvideCompletions(document, position, token, ctx);
},
resolveCompletionItem: (item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.CompletionItem => {
return this.onResolveCompletionItem(item, token);
}
};
ext.context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
templateOrParameterDocumentSelector,
completionProvider,
"'",
"[",
".",
'"',
'(',
',',
' ',
'{'
));

const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
if (activeEditor) {
const activeDocument = activeEditor.document;
Expand Down Expand Up @@ -958,34 +991,6 @@ export class AzureRMTools implements IProvideOpenedDocuments {
}
));

// tslint:disable-next-line:no-suspicious-comment
const completionProvider: vscode.CompletionItemProvider = {
provideCompletionItems: async (
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
context: vscode.CompletionContext
): Promise<vscode.CompletionList | undefined> => {
return await this.onProvideCompletions(document, position, token, context);
},
resolveCompletionItem: (item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.CompletionItem => {
return this.onResolveCompletionItem(item, token);
}
};
ext.context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
templateOrParameterDocumentSelector,
completionProvider,
"'",
"[",
".",
'"',
'(',
',',
' ',
'{'
));

// tslint:disable-next-line:no-suspicious-comment
const definitionProvider: vscode.DefinitionProvider = {
provideDefinition: async (document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Definition | undefined> => {
Expand Down Expand Up @@ -1342,15 +1347,20 @@ export class AzureRMTools implements IProvideOpenedDocuments {
return await callWithTelemetryAndErrorHandling('provideCompletionItems', async (actionContext: IActionContext): Promise<vscode.CompletionList | undefined> => {
actionContext.telemetry.suppressIfSuccessful = true;
actionContext.errorHandling.suppressDisplay = true;
actionContext.telemetry.properties.langId = document.languageId;

const cancel = new Cancellation(token, actionContext);

const pc: PositionContext | undefined = await this.getPositionContext(document, position, cancel);
let jsonDocument: IJsonDocument | undefined;
let items: Item[] | undefined;
if (pc) {
jsonDocument = pc.document;
const triggerCharacter = context.triggerKind === vscode.CompletionTriggerKind.TriggerCharacter
? context.triggerCharacter
: undefined;
const { items, triggerSuggest } = await pc.getCompletionItems(triggerCharacter, defaultTabSize);
let triggerSuggest: boolean | undefined;
({ items, triggerSuggest } = await pc.getCompletionItems(triggerCharacter, defaultTabSize));
if (triggerSuggest) {
// The user typed the beginning of a parent object, open up the completions context menu because it's
// likely they want to use a snippet immediately
Expand All @@ -1361,15 +1371,50 @@ export class AzureRMTools implements IProvideOpenedDocuments {
vscode.commands.executeCommand('editor.action.triggerSuggest');
});
return undefined;
} else {
const vsCodeItems = items.map(c => toVsCodeCompletionItem(pc.document, c, position));
ext.completionItemsSpy.postCompletionItemsResult(pc.document, items, vsCodeItems);
return new vscode.CompletionList(vsCodeItems, true);
}
} else {
const result = await this.getUnsupportedJsonSnippets(actionContext, document, position);
jsonDocument = result.jsonDocument;
items = result.items;
}

if (jsonDocument && items) {
// tslint:disable-next-line:no-non-null-assertion // Guarded with if
const vsCodeItems = items.map(c => toVsCodeCompletionItem(jsonDocument!, c, position));
ext.completionItemsSpy.postCompletionItemsResult(jsonDocument, items, vsCodeItems);
return new vscode.CompletionList(vsCodeItems, true);
}
});
}

/**
* Retrieve snippets for a JSON file that is not a deployment or parameters file
*/
private async getUnsupportedJsonSnippets(
actionContext: IActionContext,
document: vscode.TextDocument,
position: vscode.Position
): Promise<{ jsonDocument?: IJsonDocument; items?: Item[] }> {
const text = document.getText();
if (text.length > 100 /*limit size of strings we trim*/ || text.trim() !== '') {
return {};
}

// It's an empty (or whitespace) document, so we can try with the empty-document context
actionContext.telemetry.properties.isEmptyDoc = 'true';
const insertionContext: InsertionContext = {
context: KnownContexts.emptyDocument,
parents: []
};
const jsonDocument: IJsonDocument = new UnsupportedJsonDocument(document.getText(), document.uri);

const index = jsonDocument.getDocumentCharacterIndex(position.line, position.character);
const span = new Span(index, 0);
const items: Item[] = await ext.snippetManager.value.getSnippetsAsCompletionItems(insertionContext, span);

return { jsonDocument, items };
}

private onResolveCompletionItem(item: vscode.CompletionItem, _token: vscode.CancellationToken): vscode.CompletionItem {
ext.completionItemsSpy.postCompletionItemResolution(item);
return item;
Expand Down
Loading