diff --git a/package.json b/package.json index 7af119eb8..7afdc2104 100644 --- a/package.json +++ b/package.json @@ -777,6 +777,11 @@ "scope": "machine", "description": "Enables support for decompiling external references instead of viewing metadata." }, + "omnisharp.enableImportCompletion": { + "type": "boolean", + "default": false, + "description": "Enables support for showing unimported types and unimported extension methods in completion lists. When committed, the appropriate using directive will be added at the top of the current file. This option can have a negative impact on initial completion responsiveness, particularly for the first few completion sessions after opening a solution." + }, "razor.plugin.path": { "type": [ "string", diff --git a/src/features/completionItemProvider.ts b/src/features/completionItemProvider.ts deleted file mode 100644 index bea3722bc..000000000 --- a/src/features/completionItemProvider.ts +++ /dev/null @@ -1,137 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { extractSummaryText } from './documentation'; -import AbstractSupport from './abstractProvider'; -import * as protocol from '../omnisharp/protocol'; -import * as serverUtils from '../omnisharp/utils'; -import { createRequest } from '../omnisharp/typeConversion'; -import { CompletionItemProvider, CompletionItem, CompletionItemKind, CompletionContext, CompletionTriggerKind, CancellationToken, TextDocument, Range, Position, CompletionList } from 'vscode'; - -export default class OmniSharpCompletionItemProvider extends AbstractSupport implements CompletionItemProvider { - - // copied from Roslyn here: https://github.com/dotnet/roslyn/blob/6e8f6d600b6c4bc0b92bc3d782a9e0b07e1c9f8e/src/Features/Core/Portable/Completion/CompletionRules.cs#L166-L169 - private static AllCommitCharacters = [ - ' ', '{', '}', '[', ']', '(', ')', '.', ',', ':', - ';', '+', '-', '*', '/', '%', '&', '|', '^', '!', - '~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\']; - - private static CommitCharactersWithoutSpace = [ - '{', '}', '[', ']', '(', ')', '.', ',', ':', - ';', '+', '-', '*', '/', '%', '&', '|', '^', '!', - '~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\']; - - public async provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken, context: CompletionContext): Promise { - - let wordToComplete = ''; - let range = document.getWordRangeAtPosition(position); - if (range) { - wordToComplete = document.getText(new Range(range.start, position)); - } - - let req = createRequest(document, position); - req.WordToComplete = wordToComplete; - req.WantDocumentationForEveryCompletionResult = true; - req.WantKind = true; - req.WantReturnType = true; - if (context.triggerKind == CompletionTriggerKind.TriggerCharacter) { - req.TriggerCharacter = context.triggerCharacter; - } - - try { - let responses = await serverUtils.autoComplete(this._server, req, token); - - if (!responses) { - return; - } - - let result: CompletionItem[] = []; - let completions: { [c: string]: { items: CompletionItem[], preselect: boolean } } = Object.create(null); - - // transform AutoCompleteResponse to CompletionItem and - // group by code snippet - for (let response of responses) { - let completion = new CompletionItem(response.CompletionText); - - completion.detail = response.ReturnType - ? `${response.ReturnType} ${response.DisplayText}` - : response.DisplayText; - - completion.documentation = extractSummaryText(response.Description); - completion.kind = _kinds[response.Kind] || CompletionItemKind.Property; - completion.insertText = response.CompletionText.replace(/<>/g, ''); - - completion.commitCharacters = response.IsSuggestionMode - ? OmniSharpCompletionItemProvider.CommitCharactersWithoutSpace - : OmniSharpCompletionItemProvider.AllCommitCharacters; - - completion.preselect = response.Preselect; - - let completionSet = completions[completion.label]; - if (!completionSet) { - completions[completion.label] = { items: [completion], preselect: completion.preselect }; - } - else { - completionSet.preselect = completionSet.preselect || completion.preselect; - completionSet.items.push(completion); - } - } - - // per suggestion group, select on and indicate overloads - for (let key in completions) { - - let suggestion = completions[key].items[0], - overloadCount = completions[key].items.length - 1; - - if (overloadCount === 0) { - // remove non overloaded items - delete completions[key]; - - } - else { - // indicate that there is more - suggestion.detail = `${suggestion.detail} (+ ${overloadCount} overload(s))`; - suggestion.preselect = completions[key].preselect; - } - - result.push(suggestion); - } - - // for short completions (up to 1 character), treat the list as incomplete - // because the server has likely witheld some matches due to performance constraints - return new CompletionList(result, wordToComplete.length > 1 ? false : true); - } - catch (error) { - return; - } - } -} - -const _kinds: { [kind: string]: CompletionItemKind; } = Object.create(null); - -// types -_kinds['Class'] = CompletionItemKind.Class; -_kinds['Delegate'] = CompletionItemKind.Class; // need a better option for this. -_kinds['Enum'] = CompletionItemKind.Enum; -_kinds['Interface'] = CompletionItemKind.Interface; -_kinds['Struct'] = CompletionItemKind.Struct; - -// variables -_kinds['Local'] = CompletionItemKind.Variable; -_kinds['Parameter'] = CompletionItemKind.Variable; -_kinds['RangeVariable'] = CompletionItemKind.Variable; - -// members -_kinds['Const'] = CompletionItemKind.Constant; -_kinds['EnumMember'] = CompletionItemKind.EnumMember; -_kinds['Event'] = CompletionItemKind.Event; -_kinds['Field'] = CompletionItemKind.Field; -_kinds['Method'] = CompletionItemKind.Method; -_kinds['Property'] = CompletionItemKind.Property; - -// other stuff -_kinds['Label'] = CompletionItemKind.Unit; // need a better option for this. -_kinds['Keyword'] = CompletionItemKind.Keyword; -_kinds['Namespace'] = CompletionItemKind.Module; diff --git a/src/features/completionProvider.ts b/src/features/completionProvider.ts new file mode 100644 index 000000000..33069812b --- /dev/null +++ b/src/features/completionProvider.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CompletionItemProvider, TextDocument, Position, CompletionContext, CompletionList, CompletionItem, MarkdownString, TextEdit, Range, SnippetString } from "vscode"; +import AbstractProvider from "./abstractProvider"; +import * as protocol from "../omnisharp/protocol"; +import * as serverUtils from '../omnisharp/utils'; +import { CancellationToken, CompletionTriggerKind as LspCompletionTriggerKind, InsertTextFormat } from "vscode-languageserver-protocol"; +import { createRequest } from "../omnisharp/typeConversion"; + +export default class OmnisharpCompletionProvider extends AbstractProvider implements CompletionItemProvider { + + #lastCompletions?: Map; + + public async provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken, context: CompletionContext): Promise { + let request = createRequest(document, position); + request.CompletionTrigger = (context.triggerKind + 1) as LspCompletionTriggerKind; + request.TriggerCharacter = context.triggerCharacter; + + try { + const response = await serverUtils.getCompletion(this._server, request, token); + const mappedItems = response.Items.map(this._convertToVscodeCompletionItem); + + let lastCompletions = new Map(); + + for (let i = 0; i < mappedItems.length; i++) { + lastCompletions.set(mappedItems[i], response.Items[i]); + } + + this.#lastCompletions = lastCompletions; + + return { items: mappedItems }; + } + catch (error) { + return; + } + } + + public async resolveCompletionItem(item: CompletionItem, token: CancellationToken): Promise { + const lastCompletions = this.#lastCompletions; + if (!lastCompletions) { + return item; + } + + const lspItem = lastCompletions.get(item); + if (!lspItem) { + return item; + } + + const request: protocol.CompletionResolveRequest = { Item: lspItem }; + try { + const response = await serverUtils.getCompletionResolve(this._server, request, token); + return this._convertToVscodeCompletionItem(response.Item); + } + catch (error) { + return; + } + } + + private _convertToVscodeCompletionItem(omnisharpCompletion: protocol.OmnisharpCompletionItem): CompletionItem { + let docs: MarkdownString | undefined = omnisharpCompletion.Documentation ? new MarkdownString(omnisharpCompletion.Documentation, false) : undefined; + + const mapTextEdit = function (edit: protocol.LinePositionSpanTextChange): TextEdit { + const newStart = new Position(edit.StartLine - 1, edit.StartColumn - 1); + const newEnd = new Position(edit.EndLine - 1, edit.EndColumn - 1); + const newRange = new Range(newStart, newEnd); + return new TextEdit(newRange, edit.NewText); + }; + + const additionalTextEdits = omnisharpCompletion.AdditionalTextEdits?.map(mapTextEdit); + + const insertText = omnisharpCompletion.InsertTextFormat === InsertTextFormat.Snippet + ? new SnippetString(omnisharpCompletion.InsertText) + : omnisharpCompletion.InsertText; + + return { + label: omnisharpCompletion.Label, + kind: omnisharpCompletion.Kind - 1, + detail: omnisharpCompletion.Detail, + documentation: docs, + commitCharacters: omnisharpCompletion.CommitCharacters, + preselect: omnisharpCompletion.Preselect, + filterText: omnisharpCompletion.FilterText, + insertText: insertText, + tags: omnisharpCompletion.Tags, + sortText: omnisharpCompletion.SortText, + additionalTextEdits: additionalTextEdits, + keepWhitespace: true + }; + } +} diff --git a/src/observers/OptionChangeObserver.ts b/src/observers/OptionChangeObserver.ts index 877b10065..e3c445c98 100644 --- a/src/observers/OptionChangeObserver.ts +++ b/src/observers/OptionChangeObserver.ts @@ -19,7 +19,8 @@ const omniSharpOptions: ReadonlyArray = [ "waitForDebugger", "loggingLevel", "enableEditorConfigSupport", - "enableDecompilationSupport" + "enableDecompilationSupport", + "enableImportCompletion" ]; function OmniSharpOptionChangeObservable(optionObservable: Observable): Observable { diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index a71e5559b..2b2731897 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -11,7 +11,7 @@ import { safeLength, sum } from '../common'; import { CSharpConfigurationProvider } from '../configurationProvider'; import CodeActionProvider from '../features/codeActionProvider'; import CodeLensProvider from '../features/codeLensProvider'; -import CompletionItemProvider from '../features/completionItemProvider'; +import CompletionProvider from '../features/completionProvider'; import DefinitionMetadataDocumentProvider from '../features/definitionMetadataDocumentProvider'; import DefinitionProvider from '../features/definitionProvider'; import DocumentHighlightProvider from '../features/documentHighlightProvider'; @@ -90,7 +90,7 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an localDisposables.add(vscode.languages.registerDocumentRangeFormattingEditProvider(documentSelector, new FormatProvider(server, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerOnTypeFormattingEditProvider(documentSelector, new FormatProvider(server, languageMiddlewareFeature), '}', ';')); } - localDisposables.add(vscode.languages.registerCompletionItemProvider(documentSelector, new CompletionItemProvider(server, languageMiddlewareFeature), '.', ' ')); + localDisposables.add(vscode.languages.registerCompletionItemProvider(documentSelector, new CompletionProvider(server, languageMiddlewareFeature), '.', ' ')); localDisposables.add(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server, optionProvider, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerSignatureHelpProvider(documentSelector, new SignatureHelpProvider(server, languageMiddlewareFeature), '(', ',')); // Since the CodeActionProvider registers its own commands, we must instantiate it and add it to the localDisposables @@ -210,4 +210,4 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an return new Promise(resolve => server.onServerStart(e => resolve({ server, advisor, testManager }))); -} \ No newline at end of file +} diff --git a/src/omnisharp/options.ts b/src/omnisharp/options.ts index 049e1ac23..2d856ed5c 100644 --- a/src/omnisharp/options.ts +++ b/src/omnisharp/options.ts @@ -28,6 +28,7 @@ export class Options { public enableRoslynAnalyzers: boolean, public enableEditorConfigSupport: boolean, public enableDecompilationSupport: boolean, + public enableImportCompletion: boolean, public useSemanticHighlighting: boolean, public razorPluginPath?: string, public defaultLaunchSolution?: string, @@ -70,6 +71,7 @@ export class Options { const enableRoslynAnalyzers = omnisharpConfig.get('enableRoslynAnalyzers', false); const enableEditorConfigSupport = omnisharpConfig.get('enableEditorConfigSupport', false); const enableDecompilationSupport = omnisharpConfig.get('enableDecompilationSupport', false); + const enableImportCompletion = omnisharpConfig.get('enableImportCompletion', false); const useFormatting = csharpConfig.get('format.enable', true); @@ -117,6 +119,7 @@ export class Options { enableRoslynAnalyzers, enableEditorConfigSupport, enableDecompilationSupport, + enableImportCompletion, useSemanticHighlighting, razorPluginPath, defaultLaunchSolution, @@ -190,4 +193,4 @@ export class Options { return "auto"; } } -} \ No newline at end of file +} diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 6a26f4ebe..7de7f9925 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; +import { CompletionTriggerKind, CompletionItemKind, CompletionItemTag, InsertTextFormat } from 'vscode-languageserver-protocol'; export module Requests { export const AddToProject = '/addtoproject'; @@ -32,6 +33,8 @@ export module Requests { export const GetFixAll = '/getfixall'; export const ReAnalyze = '/reanalyze'; export const QuickInfo = '/quickinfo'; + export const Completion = '/completion'; + export const CompletionResolve = '/completion/resolve'; } export namespace WireProtocol { @@ -275,30 +278,6 @@ export interface SyntaxFeature { Data: string; } -export interface AutoCompleteRequest extends Request { - WordToComplete: string; - WantDocumentationForEveryCompletionResult?: boolean; - WantImportableTypes?: boolean; - WantMethodHeader?: boolean; - WantSnippet?: boolean; - WantReturnType?: boolean; - WantKind?: boolean; - TriggerCharacter?: string; -} - -export interface AutoCompleteResponse { - CompletionText: string; - Description: string; - DisplayText: string; - RequiredNamespaceImport: string; - MethodHeader: string; - ReturnType: string; - Snippet: string; - Kind: string; - IsSuggestionMode: boolean; - Preselect: boolean; -} - export interface ProjectInformationResponse { MsBuildProject: MSBuildProject; } @@ -507,7 +486,7 @@ export interface RunFixAllRequest extends FileBasedRequest { WantsTextChanges: boolean; WantsAllCodeActionOperations: boolean; } - + export interface QuickInfoRequest extends Request { } @@ -515,6 +494,40 @@ export interface QuickInfoResponse { Markdown?: string; } +export interface CompletionRequest extends Request { + CompletionTrigger: CompletionTriggerKind; + TriggerCharacter?: string; +} + +export interface CompletionResponse { + IsIncomplete: boolean; + Items: OmnisharpCompletionItem[]; +} + +export interface CompletionResolveRequest { + Item: OmnisharpCompletionItem; +} + +export interface CompletionResolveResponse { + Item: OmnisharpCompletionItem; +} + +export interface OmnisharpCompletionItem { + Label: string; + Kind: CompletionItemKind; + Tags?: CompletionItemTag[]; + Detail?: string; + Documentation?: string; + Preselect: boolean; + SortText?: string; + FilterText?: string; + InsertText?: string; + InsertTextFormat?: InsertTextFormat; + CommitCharacters?: string[]; + AdditionalTextEdits?: LinePositionSpanTextChange[]; + Data: any; +} + export namespace V2 { export module Requests { diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 9ce62b5d9..4384e0f76 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -353,6 +353,10 @@ export class OmniSharpServer { args.push('RoslynExtensionsOptions:EnableDecompilationSupport=true'); } + if (options.enableImportCompletion === true) { + args.push('RoslynExtensionsOptions:EnableImportCompletion=true'); + } + let launchInfo: LaunchInfo; try { launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this.packageJSON.defaults.omniSharp, options.path, serverUrl, latestVersionFileServerPath, installPath, this.extensionPath); diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 9109a0a27..873d7e198 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -11,10 +11,6 @@ import * as vscode from 'vscode'; import { MSBuildProject } from './protocol'; import { CancellationToken } from 'vscode-languageserver-protocol'; -export async function autoComplete(server: OmniSharpServer, request: protocol.AutoCompleteRequest, token: vscode.CancellationToken) { - return server.makeRequest(protocol.Requests.AutoComplete, request, token); -} - export async function codeCheck(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.CodeCheck, request, token); } @@ -181,6 +177,14 @@ export async function getQuickInfo(server: OmniSharpServer, request: protocol.Qu return server.makeRequest(protocol.Requests.QuickInfo, request, token); } +export async function getCompletion(server: OmniSharpServer, request: protocol.CompletionRequest, context: vscode.CancellationToken) { + return server.makeRequest(protocol.Requests.Completion, request, context); +} + +export async function getCompletionResolve(server: OmniSharpServer, request: protocol.CompletionResolveRequest, context: vscode.CancellationToken) { + return server.makeRequest(protocol.Requests.CompletionResolve, request, context); +} + export async function isNetCoreProject(project: protocol.MSBuildProject) { return project.TargetFrameworks.find(tf => tf.ShortName.startsWith('netcoreapp') || tf.ShortName.startsWith('netstandard')) !== undefined; } diff --git a/test/integrationTests/completionItemProvider.integration.test.ts b/test/integrationTests/completionItemProvider.integration.test.ts deleted file mode 100644 index 8615319fd..000000000 --- a/test/integrationTests/completionItemProvider.integration.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - -import OmniSharpCompletionItemProvider from "../../src/features/completionItemProvider"; -import * as vscode from 'vscode'; -import testAssetWorkspace from "./testAssets/testAssetWorkspace"; -import * as path from "path"; -import { expect } from "chai"; -import { activateCSharpExtension, isRazorWorkspace } from "./integrationHelpers"; - -suite(`${OmniSharpCompletionItemProvider.name}: Returns the completion items`, () => { - let fileUri: vscode.Uri; - - suiteSetup(async function () { - // These tests don't run on the BasicRazorApp2_1 solution - if (isRazorWorkspace(vscode.workspace)) { - this.skip(); - } - - await activateCSharpExtension(); - await testAssetWorkspace.restore(); - - let fileName = 'completion.cs'; - let dir = testAssetWorkspace.projects[0].projectDirectoryPath; - fileUri = vscode.Uri.file(path.join(dir, fileName)); - await vscode.commands.executeCommand("vscode.open", fileUri); - }); - - suiteTeardown(async () => { - await testAssetWorkspace.cleanupWorkspace(); - }); - - test("Returns the completion items", async () => { - let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(8, 31), " ")); - expect(completionList.items).to.not.be.empty; - }); - - test("Preselect is enabled for atleast one completionItem when there is a new", async () => { - let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(8, 31), " ")); - let preselectList = completionList.items.filter(item => item.preselect === true); - expect(preselectList).to.not.be.empty; - }); -}); \ No newline at end of file diff --git a/test/integrationTests/completionProvider.integration.test.ts b/test/integrationTests/completionProvider.integration.test.ts new file mode 100644 index 000000000..99d769c62 --- /dev/null +++ b/test/integrationTests/completionProvider.integration.test.ts @@ -0,0 +1,71 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +*--------------------------------------------------------------------------------------------*/ + +import OmniSharpCompletionProvider from "../../src/features/completionProvider"; +import * as vscode from 'vscode'; +import testAssetWorkspace from "./testAssets/testAssetWorkspace"; +import * as path from "path"; +import { expect } from "chai"; +import { activateCSharpExtension, isRazorWorkspace } from "./integrationHelpers"; + +suite(`${OmniSharpCompletionProvider.name}: Returns the completion items`, () => { + let fileUri: vscode.Uri; + + suiteSetup(async function () { + // These tests don't run on the BasicRazorApp2_1 solution + if (isRazorWorkspace(vscode.workspace)) { + this.skip(); + } + + await activateCSharpExtension(); + await testAssetWorkspace.restore(); + + let fileName = 'completion.cs'; + let dir = testAssetWorkspace.projects[0].projectDirectoryPath; + fileUri = vscode.Uri.file(path.join(dir, fileName)); + await vscode.commands.executeCommand("vscode.open", fileUri); + + // The override bit is commented out to allow later debugging to work correctly. + let overrideUncomment = new vscode.WorkspaceEdit(); + overrideUncomment.delete(fileUri, new vscode.Range(new vscode.Position(11, 8), new vscode.Position(11, 11))); + await vscode.workspace.applyEdit(overrideUncomment); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); + + test("Returns the completion items", async () => { + let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(8, 31), " ")); + expect(completionList.items).to.not.be.empty; + }); + + test("Preselect is enabled for at least one completionItem when there is a new", async () => { + let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(8, 31), " ")); + let preselectList = completionList.items.filter(item => item.preselect === true); + expect(preselectList).to.not.be.empty; + }); + + test("Resolve adds documentation", async () => { + let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(8, 31), " ", 10)); + // At least some of the first 10 fully-resolved elements should have documentation attached. If this ever ends up not being + // true, adjust the cutoff appropriately. + const documentation = completionList.items.slice(0, 9).filter(item => item.documentation); + expect(documentation).to.not.be.empty; + }); + + test("Override completion has additional edits", async () => { + let completionList = (await vscode.commands.executeCommand("vscode.executeCompletionItemProvider", fileUri, new vscode.Position(11, 17), " ")); + const nonSnippets = completionList.items.filter(c => c.kind != vscode.CompletionItemKind.Snippet); + for (const i of nonSnippets) { + expect((i.insertText).value).contains("$0"); + expect(i.additionalTextEdits).is.not.null; + expect(i.additionalTextEdits[0].range.start.line).equals(11); + expect(i.additionalTextEdits[0].range.start.character).equals(8); + expect(i.additionalTextEdits[0].range.end.line).equals(11); + expect(i.additionalTextEdits[0].range.end.character).equals(16); + } + }); +}); diff --git a/test/integrationTests/testAssets/singleCsproj/completion.cs b/test/integrationTests/testAssets/singleCsproj/completion.cs index e844bc954..9059e4e92 100644 --- a/test/integrationTests/testAssets/singleCsproj/completion.cs +++ b/test/integrationTests/testAssets/singleCsproj/completion.cs @@ -8,5 +8,7 @@ static void shouldHaveCompletions(string[] args) { Completion a = new Completion(); } + + // override // Trailing space is intentional } } diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs index 715d21ebc..9059e4e92 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs @@ -6,7 +6,9 @@ class Completion { static void shouldHaveCompletions(string[] args) { - Completion a = new Completion(); + Completion a = new Completion(); } + + // override // Trailing space is intentional } } diff --git a/test/unitTests/Fakes/FakeOptions.ts b/test/unitTests/Fakes/FakeOptions.ts index 638d3214b..07885d295 100644 --- a/test/unitTests/Fakes/FakeOptions.ts +++ b/test/unitTests/Fakes/FakeOptions.ts @@ -6,5 +6,5 @@ import { Options } from "../../../src/omnisharp/options"; export function getEmptyOptions(): Options { - return new Options("", "", false, "", false, 0, 0, false, false, false, false, false, false, 0, 0, false, false, false, false, false, false, undefined, "", ""); + return new Options("", "", false, "", false, 0, 0, false, false, false, false, false, false, 0, 0, false, false, false, false, false, false, false, undefined, "", ""); } diff --git a/test/unitTests/optionStream.test.ts b/test/unitTests/optionStream.test.ts index 2fe2a6b49..21559e107 100644 --- a/test/unitTests/optionStream.test.ts +++ b/test/unitTests/optionStream.test.ts @@ -54,6 +54,7 @@ suite('OptionStream', () => { options.enableRoslynAnalyzers.should.equal(false); options.enableEditorConfigSupport.should.equal(false); options.enableDecompilationSupport.should.equal(false); + options.enableImportCompletion.should.equal(false); expect(options.defaultLaunchSolution).to.be.undefined; }); @@ -103,4 +104,4 @@ suite('OptionStream', () => { return vscode; } -}); \ No newline at end of file +}); diff --git a/test/unitTests/options.test.ts b/test/unitTests/options.test.ts index 88ac39b84..a314a1dbc 100644 --- a/test/unitTests/options.test.ts +++ b/test/unitTests/options.test.ts @@ -33,6 +33,7 @@ suite("Options tests", () => { options.enableRoslynAnalyzers.should.equal(false); options.enableEditorConfigSupport.should.equal(false); options.enableDecompilationSupport.should.equal(false); + options.enableImportCompletion.should.equal(false); expect(options.defaultLaunchSolution).to.be.undefined; });