diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs
new file mode 100644
index 0000000000000..9f85df7d0f60b
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs
@@ -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 =
+ $@"
+
+
+
+$$
+
+
+root = true
+
+[*]
+# IDE0008: Use explicit type
+dotnet_style_require_accessibility_modifiers = always
+
+
+";
+ 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);
+ }
+ }
+}
diff --git a/src/Features/CSharp/Portable/Snippets/CSharpInterfaceSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/CSharpInterfaceSnippetProvider.cs
new file mode 100644
index 0000000000000..87b37095e1be1
--- /dev/null
+++ b/src/Features/CSharp/Portable/Snippets/CSharpInterfaceSnippetProvider.cs
@@ -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 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 GetSnippetContainerFunction(ISyntaxFacts syntaxFacts)
+ {
+ return syntaxFacts.IsInterfaceDeclaration;
+ }
+ }
+}
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
index cb8392ed54f88..8a1c40805b0f0 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs
@@ -124,6 +124,7 @@ public TSyntaxKind Convert(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;
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
index 46ed2837ff877..6b9228b623e5e 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs
@@ -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;
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
index 8e6c6211c16e8..b6a15d53c6cb0 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs
@@ -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; }
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
index f418b5fd9e5b9..1ce6a58163ecf 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb
@@ -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