diff --git a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
index e14e82032ac9c..9840f4ec58e31 100644
--- a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
+++ b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
@@ -619,4 +619,7 @@
do-while loop
{Locked="do"}{Locked="while"} "do" and "while" are C# keywords and should not be localized.
+
+ required property
+
\ No newline at end of file
diff --git a/src/Features/CSharp/Portable/Snippets/AbstractCSharpAutoPropertySnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/AbstractCSharpAutoPropertySnippetProvider.cs
index 9e6a532dd26f2..71db65b2cab5a 100644
--- a/src/Features/CSharp/Portable/Snippets/AbstractCSharpAutoPropertySnippetProvider.cs
+++ b/src/Features/CSharp/Portable/Snippets/AbstractCSharpAutoPropertySnippetProvider.cs
@@ -30,6 +30,8 @@ internal abstract class AbstractCSharpAutoPropertySnippetProvider : AbstractProp
protected virtual AccessorDeclarationSyntax? GenerateSetAccessorDeclaration(CSharpSyntaxContext syntaxContext, SyntaxGenerator generator, CancellationToken cancellationToken)
=> (AccessorDeclarationSyntax)generator.SetAccessorDeclaration();
+ protected virtual SyntaxToken[] GetAdditionalPropertyModifiers(CSharpSyntaxContext? syntaxContext) => [];
+
protected override bool IsValidSnippetLocationCore(SnippetContext context, CancellationToken cancellationToken)
{
return context.SyntaxContext.SyntaxTree.IsMemberDeclarationContext(context.Position, (CSharpSyntaxContext)context.SyntaxContext,
@@ -58,6 +60,8 @@ protected override async Task GenerateSnippetSyntaxAs
modifiers = SyntaxTokenList.Create(PublicKeyword);
}
+ modifiers = modifiers.AddRange(GetAdditionalPropertyModifiers(syntaxContext));
+
return SyntaxFactory.PropertyDeclaration(
attributeLists: default,
modifiers: modifiers,
diff --git a/src/Features/CSharp/Portable/Snippets/CSharpProprSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/CSharpProprSnippetProvider.cs
new file mode 100644
index 0000000000000..d1444d0fa1984
--- /dev/null
+++ b/src/Features/CSharp/Portable/Snippets/CSharpProprSnippetProvider.cs
@@ -0,0 +1,65 @@
+// 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.Composition;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.Snippets;
+using Microsoft.CodeAnalysis.Snippets.SnippetProviders;
+using static Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTokens;
+
+namespace Microsoft.CodeAnalysis.CSharp.Snippets;
+
+[ExportSnippetProvider(nameof(ISnippetProvider), LanguageNames.CSharp), Shared]
+[method: ImportingConstructor]
+[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
+internal sealed class CSharpProprSnippetProvider() : AbstractCSharpAutoPropertySnippetProvider
+{
+ public override string Identifier => CSharpSnippetIdentifiers.RequiredProperty;
+
+ public override string Description => CSharpFeaturesResources.required_property;
+
+ protected override SyntaxToken[] GetAdditionalPropertyModifiers(CSharpSyntaxContext? syntaxContext) => [RequiredKeyword];
+
+ protected override bool IsValidSnippetLocationCore(SnippetContext context, CancellationToken cancellationToken)
+ {
+ if (!base.IsValidSnippetLocationCore(context, cancellationToken))
+ return false;
+
+ var syntaxContext = (CSharpSyntaxContext)context.SyntaxContext;
+ var precedingModifiers = syntaxContext.PrecedingModifiers;
+
+ // The required modifier can't be applied to members of an interface
+ if (syntaxContext.ContainingTypeDeclaration is InterfaceDeclarationSyntax)
+ return false;
+
+ // "protected internal" modifiers are valid for required property
+ if (precedingModifiers.IsSupersetOf([SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword]))
+ return true;
+
+ // "private", "private protected", "protected" and "private protected" modifiers are NOT valid for required property
+ if (precedingModifiers.Any(syntaxKind => syntaxKind is SyntaxKind.PrivateKeyword or SyntaxKind.ProtectedKeyword))
+ return false;
+
+ return true;
+ }
+
+ protected override AccessorDeclarationSyntax? GenerateSetAccessorDeclaration(CSharpSyntaxContext syntaxContext, SyntaxGenerator generator, CancellationToken cancellationToken)
+ {
+ // Having a property with `set` accessor in a readonly struct leads to a compiler error.
+ // So if user executes snippet inside a readonly struct the right thing to do is to not generate `set` accessor at all
+ if (syntaxContext.ContainingTypeDeclaration is StructDeclarationSyntax structDeclaration &&
+ syntaxContext.SemanticModel.GetDeclaredSymbol(structDeclaration, cancellationToken) is { IsReadOnly: true })
+ {
+ return null;
+ }
+
+ return base.GenerateSetAccessorDeclaration(syntaxContext, generator, cancellationToken);
+ }
+}
diff --git a/src/Features/CSharp/Portable/Snippets/CSharpSnippetIdentifiers.cs b/src/Features/CSharp/Portable/Snippets/CSharpSnippetIdentifiers.cs
index f2c39f292e8d3..406a380e2ca8a 100644
--- a/src/Features/CSharp/Portable/Snippets/CSharpSnippetIdentifiers.cs
+++ b/src/Features/CSharp/Portable/Snippets/CSharpSnippetIdentifiers.cs
@@ -18,6 +18,7 @@ internal static class CSharpSnippetIdentifiers
public const string ReversedFor = "forr";
public const string ForEach = "foreach";
public const string InitOnlyProperty = "propi";
+ public const string RequiredProperty = "propr";
public const string If = "if";
public const string Interface = "interface";
public const string Lock = "lock";
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
index 7c277d113addf..a52b85765ae30 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
@@ -432,6 +432,11 @@
struktura záznamu
+
+
+ required property
+
+
obrácená smyčka typu for
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
index 43abdee07e7c8..1a1367d42d040 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
@@ -432,6 +432,11 @@
Datensatzstruktur
+
+
+ required property
+
+
reversed for-Schleife
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
index fb1506e889134..c93710402b6aa 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
@@ -432,6 +432,11 @@
registro de estructuras
+
+
+ required property
+
+
bucle for invertido
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
index c3660c23351bb..343234c206710 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
@@ -432,6 +432,11 @@
struct d’enregistrement
+
+
+ required property
+
+
boucle for inversée
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
index d781f9904657c..c80b27b78ea29 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
@@ -432,6 +432,11 @@
struct di record
+
+
+ required property
+
+
invertito for loop
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
index 261bbf1413967..f52983cb5b515 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
@@ -432,6 +432,11 @@
レコード構造体
+
+
+ required property
+
+
逆 for ループ
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
index 5bc2e5b7bcf2e..d9ecd34b88674 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
@@ -432,6 +432,11 @@
레코드 구조체
+
+
+ required property
+
+
for 루프 대해 반전
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
index af1a6a9a74558..e42d24a561225 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
@@ -432,6 +432,11 @@
struktura rekordów
+
+
+ required property
+
+
odwrócona pętla for
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
index 8a38cb15bb1ec..9a67ba4d06d54 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
@@ -432,6 +432,11 @@
registrar struct
+
+
+ required property
+
+
loop for invertido
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
index fba75ab606895..b22d9ae9aa674 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
@@ -432,6 +432,11 @@
структура записей
+
+
+ required property
+
+
перевернутый for цикла
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
index ee5a5cf4b1dcb..dbbe9998b322c 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
@@ -432,6 +432,11 @@
kayıt yapısı
+
+
+ required property
+
+
ters for döngüsü
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
index 241b9c403b1b2..5ce1d189d6f4c 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
@@ -432,6 +432,11 @@
记录结构
+
+
+ required property
+
+
反转的 for 循环
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
index 645b87cd0be55..bb5d3d9f4a30b 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
@@ -432,6 +432,11 @@
記錄結構
+
+
+ required property
+
+
反轉 for 迴圈
diff --git a/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs
index 8dbe4ef2d7abb..81c5812d9be3a 100644
--- a/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs
+++ b/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs
@@ -56,11 +56,14 @@ class MyClass
""");
}
- [Fact]
- public async Task InsertSnippetInRecordTest()
+ [Theory]
+ [InlineData("record")]
+ [InlineData("record struct")]
+ [InlineData("record class")]
+ public async Task InsertSnippetInRecordTest(string recordType)
{
- await VerifyDefaultPropertyAsync("""
- record MyRecord
+ await VerifyDefaultPropertyAsync($$"""
+ {{recordType}} MyRecord
{
$$
}
@@ -90,7 +93,7 @@ struct MyStruct
// This case might produce non-default results for different snippets (e.g. no `set` accessor in 'propg' snippet),
// so it is tested separately for all of them
[Fact]
- public abstract Task InsertSnippetInInterfaceTest();
+ public abstract Task VerifySnippetInInterfaceTest();
[Fact]
public async Task InsertSnippetNamingTest()
@@ -143,9 +146,7 @@ public Program()
""");
}
- [Theory]
- [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))]
- public async Task InsertSnippetAfterAccessibilityModifierTest(string modifier)
+ public virtual async Task InsertSnippetAfterAllowedAccessibilityModifierTest(string modifier)
{
await VerifyPropertyAsync($$"""
class Program
@@ -162,6 +163,6 @@ protected async Task VerifyPropertyAsync([StringSyntax(PredefinedEmbeddedLanguag
await VerifySnippetAsync(markup, expectedCode);
}
- protected Task VerifyDefaultPropertyAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, string propertyName = "MyProperty")
+ protected virtual Task VerifyDefaultPropertyAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, string propertyName = "MyProperty")
=> VerifyPropertyAsync(markup, $$"""public {|0:int|} {|1:{{propertyName}}|} {{DefaultPropertyBlockText}}""");
}
diff --git a/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs
index 903f9d6a2b942..5b13ab35d4a6e 100644
--- a/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs
+++ b/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
+using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets;
@@ -56,7 +57,7 @@ readonly partial struct MyStruct
""", "public {|0:int|} {|1:MyProperty|} { get; }");
}
- public override async Task InsertSnippetInInterfaceTest()
+ public override async Task VerifySnippetInInterfaceTest()
{
await VerifyDefaultPropertyAsync("""
interface MyInterface
@@ -65,4 +66,9 @@ interface MyInterface
}
""");
}
+
+ [Theory]
+ [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))]
+ public override Task InsertSnippetAfterAllowedAccessibilityModifierTest(string modifier)
+ => base.InsertSnippetAfterAllowedAccessibilityModifierTest(modifier);
}
diff --git a/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs
index d4413d32e9bc5..2f4a46a5ea84d 100644
--- a/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs
+++ b/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
+using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets;
@@ -56,7 +57,7 @@ readonly partial struct MyStruct
""", "public {|0:int|} {|1:MyProperty|} { get; }");
}
- public override async Task InsertSnippetInInterfaceTest()
+ public override async Task VerifySnippetInInterfaceTest()
{
// Ensure we don't generate redundant `set` accessor when executed in interface
await VerifyPropertyAsync("""
@@ -66,4 +67,9 @@ interface MyInterface
}
""", "public {|0:int|} {|1:MyProperty|} { get; }");
}
+
+ [Theory]
+ [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))]
+ public override Task InsertSnippetAfterAllowedAccessibilityModifierTest(string modifier)
+ => base.InsertSnippetAfterAllowedAccessibilityModifierTest(modifier);
}
diff --git a/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs
index 880dcf3a70927..38ab037b43245 100644
--- a/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs
+++ b/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
+using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets;
@@ -50,7 +51,7 @@ readonly partial struct MyStruct
""");
}
- public override async Task InsertSnippetInInterfaceTest()
+ public override async Task VerifySnippetInInterfaceTest()
{
await VerifyDefaultPropertyAsync("""
interface MyInterface
@@ -59,4 +60,9 @@ interface MyInterface
}
""");
}
+
+ [Theory]
+ [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))]
+ public override Task InsertSnippetAfterAllowedAccessibilityModifierTest(string modifier)
+ => base.InsertSnippetAfterAllowedAccessibilityModifierTest(modifier);
}
diff --git a/src/Features/CSharpTest/Snippets/CSharpProprSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpProprSnippetProviderTests.cs
new file mode 100644
index 0000000000000..5f75aef2b5a01
--- /dev/null
+++ b/src/Features/CSharpTest/Snippets/CSharpProprSnippetProviderTests.cs
@@ -0,0 +1,102 @@
+// 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.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets;
+
+public sealed class CSharpProprSnippetProviderTests : AbstractCSharpAutoPropertySnippetProviderTests
+{
+ protected override string SnippetIdentifier => "propr";
+
+ protected override string DefaultPropertyBlockText => "{ get; set; }";
+
+ public override async Task InsertSnippetInReadonlyStructTest()
+ {
+ // Ensure we don't generate redundant `set` accessor when executed in readonly struct
+ await VerifyPropertyAsync("""
+ readonly struct MyStruct
+ {
+ $$
+ }
+ """, "public required {|0:int|} {|1:MyProperty|} { get; }");
+ }
+
+ public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration()
+ {
+ // Ensure we don't generate redundant `set` accessor when executed in readonly struct
+ await VerifyPropertyAsync("""
+ partial struct MyStruct
+ {
+ $$
+ }
+
+ readonly partial struct MyStruct
+ {
+ }
+ """, "public required {|0:int|} {|1:MyProperty|} { get; }");
+ }
+
+ public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier()
+ {
+ // Even though there is no `partial` modifier on the first declaration
+ // compiler still treats the whole type as partial since it is more likely that
+ // the user's intent was to have a partial type and they just forgot the modifier.
+ // Thus we still recognize that as `readonly` context and don't generate a setter
+ await VerifyPropertyAsync("""
+ struct MyStruct
+ {
+ $$
+ }
+
+ readonly partial struct MyStruct
+ {
+ }
+ """, "public required {|0:int|} {|1:MyProperty|} { get; }");
+ }
+
+ public override async Task VerifySnippetInInterfaceTest()
+ {
+ await VerifySnippetIsAbsentAsync("""
+ interface MyInterface
+ {
+ $$
+ }
+ """);
+ }
+
+ [Theory]
+ [InlineData("public")]
+ [InlineData("internal")]
+ [InlineData("protected internal")]
+ public override async Task InsertSnippetAfterAllowedAccessibilityModifierTest(string modifier)
+ {
+ await VerifyPropertyAsync($$"""
+ class Program
+ {
+ {{modifier}} $$
+ }
+ """, $$"""required {|0:int|} {|1:MyProperty|} {{DefaultPropertyBlockText}}""");
+ }
+
+ [Theory]
+ [InlineData("private")]
+ [InlineData("protected")]
+ [InlineData("private protected")]
+ public async Task NoSnippetAfterWrongAccessibilityModifierTest(string modifier)
+ {
+ await VerifySnippetIsAbsentAsync($$"""
+ class Program
+ {
+ {{modifier}} $$
+ }
+ """);
+ }
+
+ protected override Task VerifyDefaultPropertyAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, string propertyName = "MyProperty")
+ => VerifyPropertyAsync(markup, $$"""public required {|0:int|} {|1:{{propertyName}}|} {{DefaultPropertyBlockText}}""");
+}