Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets
{
[Trait(Traits.Feature, Traits.Features.Completion)]
public class CSharpInterfaceSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests
{
protected override string ItemToCommit => "interface";

[WpfFact]
public async Task InsertInterfaceSnippetInNamespaceTest()
{
var markupBeforeCommit =
@"namespace Namespace
{
$$
}";

var expectedCodeAfterCommit =
@"namespace Namespace
{
interface MyInterface
{
$$
}
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetInFileScopedNamespaceTest()
{
var markupBeforeCommit =
@"namespace Namespace;

$$";

var expectedCodeAfterCommit =
@"namespace Namespace;

interface MyInterface
{
$$
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetTest()
{
var markupBeforeCommit =
@"$$";

var expectedCodeAfterCommit =
@"interface MyInterface
{
$$
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceTopLevelSnippetTest()
{
var markupBeforeCommit =
@"System.Console.WriteLine();
$$";

var expectedCodeAfterCommit =
@"System.Console.WriteLine();

interface MyInterface
{
$$
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetInClassTest()
{
var markupBeforeCommit =
@"class MyClass
{
$$
}";

var expectedCodeAfterCommit =
@"class MyClass
{
interface MyInterface
{
$$
}
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetInRecordTest()
{
var markupBeforeCommit =
@"record MyRecord
{
$$
}";

var expectedCodeAfterCommit =
@"record MyRecord
{
interface MyInterface
{
$$
}
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetInStructTest()
{
var markupBeforeCommit =
@"struct MyStruct
{
$$
}";

var expectedCodeAfterCommit =
@"struct MyStruct
{
interface MyInterface
{
$$
}
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetInInterfaceTest()
{
var markupBeforeCommit =
@"interface MyInterface
{
$$
}";

var expectedCodeAfterCommit =
@"interface MyInterface
{
interface MyInterface1
{
$$
}
}";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task InsertInterfaceSnippetWithModifiersTest()
{
var markupBeforeCommit =
$@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document FilePath=""/0/Test0.cs"">
$$
</Document>
<AnalyzerConfigDocument FilePath=""/.editorconfig"">
root = true

[*]
# IDE0008: Use explicit type
dotnet_style_require_accessibility_modifiers = always
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expectedCodeAfterCommit =
$@"
public interface MyInterface
{{
$$
}}
";
await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit);
}

[WpfFact]
public async Task NoInterfaceSnippetInEnumTest()
{
var markupBeforeCommit =
@"enum MyEnum
{
$$
}";

await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit);
}

[WpfFact]
public async Task NoInteraceSnippetInMethodTest()
{
var markupBeforeCommit =
@"class Program
{
public void Method()
{
$$
}
}";
await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit);
}

[WpfFact]
public async Task NoInterfaceSnippetInConstructorTest()
{
var markupBeforeCommit =
@"class Program
{
public Program()
{
$$
}
}";
await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Composition;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Snippets;
using Microsoft.CodeAnalysis.Snippets.SnippetProviders;

namespace Microsoft.CodeAnalysis.CSharp.Snippets
{
[ExportSnippetProvider(nameof(ISnippetProvider), LanguageNames.CSharp), Shared]
internal class CSharpInterfaceSnippetProvider : CSharpTypeSnippetProvider
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpInterfaceSnippetProvider()
{
}

public override string SnippetIdentifier => "interface";

public override string SnippetDescription => FeaturesResources.interface_;

protected override async Task<SyntaxNode> GenerateTypeDeclarationAsync(Document document, int position, bool useAccessibility, CancellationToken cancellationToken)
{
var generator = SyntaxGenerator.GetGenerator(document);
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

var name = NameGenerator.GenerateUniqueName("MyInterface", name => semanticModel.LookupSymbols(position, name: name).IsEmpty);
return useAccessibility is true
? generator.InterfaceDeclaration(name, accessibility: Accessibility.Public)
: generator.InterfaceDeclaration(name);
}

protected override Func<SyntaxNode?, bool> GetSnippetContainerFunction(ISyntaxFacts syntaxFacts)
{
return syntaxFacts.IsInterfaceDeclaration;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public TSyntaxKind Convert<TSyntaxKind>(int kind) where TSyntaxKind : struct

public int Attribute => (int)SyntaxKind.Attribute;
public int ClassDeclaration => (int)SyntaxKind.ClassDeclaration;
public int InterfaceDeclaration => (int)SyntaxKind.InterfaceDeclaration;
public int? RecordDeclaration => (int)SyntaxKind.RecordDeclaration;
public int? RecordStructDeclaration => (int)SyntaxKind.RecordStructDeclaration;
public int? StructDeclaration => (int)SyntaxKind.StructDeclaration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,9 @@ public static bool IsClassDeclaration(this ISyntaxFacts syntaxFacts, [NotNullWhe
public static bool IsGlobalAttribute(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
=> syntaxFacts.IsGlobalAssemblyAttribute(node) || syntaxFacts.IsGlobalModuleAttribute(node);

public static bool IsInterfaceDeclaration(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
=> node?.RawKind == syntaxFacts.SyntaxKinds.InterfaceDeclaration;

public static bool IsParameter(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
=> node?.RawKind == syntaxFacts.SyntaxKinds.Parameter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ internal interface ISyntaxKinds

int Attribute { get; }
int ClassDeclaration { get; }
int InterfaceDeclaration { get; }
int? RecordDeclaration { get; }
int? RecordStructDeclaration { get; }
int? StructDeclaration { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService

Public ReadOnly Property Attribute As Integer = SyntaxKind.Attribute Implements ISyntaxKinds.Attribute
Public ReadOnly Property ClassDeclaration As Integer = SyntaxKind.ClassBlock Implements ISyntaxKinds.ClassDeclaration
Public ReadOnly Property InterfaceDeclaration As Integer = SyntaxKind.InterfaceBlock Implements ISyntaxKinds.InterfaceDeclaration
Public ReadOnly Property RecordDeclaration As Integer? Implements ISyntaxKinds.RecordDeclaration
Public ReadOnly Property RecordStructDeclaration As Integer? Implements ISyntaxKinds.RecordStructDeclaration
Public ReadOnly Property StructDeclaration As Integer? Implements ISyntaxKinds.StructDeclaration
Expand Down