diff --git a/src/Sharpen.Engine/Sharpen.Engine.csproj b/src/Sharpen.Engine/Sharpen.Engine.csproj index c23cb3c..eb514b9 100644 --- a/src/Sharpen.Engine/Sharpen.Engine.csproj +++ b/src/Sharpen.Engine/Sharpen.Engine.csproj @@ -233,6 +233,7 @@ + diff --git a/src/Sharpen.Engine/SharpenEngine.cs b/src/Sharpen.Engine/SharpenEngine.cs index 15e8d00..c22cb31 100644 --- a/src/Sharpen.Engine/SharpenEngine.cs +++ b/src/Sharpen.Engine/SharpenEngine.cs @@ -23,6 +23,7 @@ public class SharpenEngine UseExpressionBodyForGetOnlyIndexers.Instance, UseNameofExpressionForThrowingArgumentExceptions.Instance, + UseNameofExpressionInDependencyPropertyDeclarations.Instance, // C# 7.0. UseExpressionBodyForConstructors.Instance, diff --git a/src/Sharpen.Engine/SharpenSuggestions/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations.cs b/src/Sharpen.Engine/SharpenSuggestions/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations.cs new file mode 100644 index 0000000..99e2738 --- /dev/null +++ b/src/Sharpen.Engine/SharpenSuggestions/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Sharpen.Engine.Extensions; + +namespace Sharpen.Engine.SharpenSuggestions.CSharp60.NameofExpressions +{ + internal sealed class UseNameofExpressionInDependencyPropertyDeclarations : ISharpenSuggestion, ISingleSyntaxTreeAnalyzer + { + private static readonly SyntaxKind[] RequiredDependencyPropertyFieldModifiers = { SyntaxKind.ReadOnlyKeyword, SyntaxKind.StaticKeyword }; + private static readonly ArgumentSyntax[] EmptyArgumentSyntaxArray = new ArgumentSyntax[0]; + + private UseNameofExpressionInDependencyPropertyDeclarations() { } + + public string MinimumLanguageVersion { get; } = CSharpLanguageVersions.CSharp60; + + public ICSharpFeature LanguageFeature { get; } = CSharpFeatures.NameofExpressions.Instance; + + public string FriendlyName { get; } = "Use nameof expression in dependency property declarations"; + + public static readonly UseNameofExpressionInDependencyPropertyDeclarations Instance = new UseNameofExpressionInDependencyPropertyDeclarations(); + + private static string GetRegisterMethodDisplayText(SyntaxNode syntaxNode) // SyntaxNode is actually ArgumentSyntax. + { + return syntaxNode.FirstAncestorOrSelf().ToString(); + } + + public IEnumerable Analyze(SyntaxTree syntaxTree, SemanticModel semanticModel, SingleSyntaxTreeAnalysisContext analysisContext) + { + return syntaxTree.GetRoot() + .DescendantNodes() + .OfType() + .Select(GetPropertyNameArgumentsIfFieldDeclarationIsDependencyPropertyDeclaration) + .Where(propertyNames => propertyNames.Length > 0) + .SelectMany(propertyNames => propertyNames) + .Select(propertyName => new AnalysisResult + ( + this, + analysisContext, + syntaxTree.FilePath, + propertyName.GetFirstToken(), + propertyName, + GetRegisterMethodDisplayText + )); + + ArgumentSyntax[] GetPropertyNameArgumentsIfFieldDeclarationIsDependencyPropertyDeclaration(FieldDeclarationSyntax fieldDeclaration) + { + // Let's first do fast checks that quickly and cheaply eliminate obvious non-candidates. + // We want to use the semantic model only if we are sure that we have candidates that are + // very likely field declarations that we are looking for. + + if (!(RequiredDependencyPropertyFieldModifiers.All(modifier => + fieldDeclaration.Modifiers.Select(token => token.Kind()).Contains(modifier)) && + fieldDeclaration.Declaration.Type.GetLastToken().ValueText == "DependencyProperty")) + return EmptyArgumentSyntaxArray; + + return fieldDeclaration + .Declaration + .Variables + .Where(variableDeclaration => + variableDeclaration.Identifier.ValueText.EndsWith("Property", StringComparison.Ordinal) && + variableDeclaration.Initializer != null && + variableDeclaration.Initializer.Value.IsKind(SyntaxKind.InvocationExpression)) + .Select(variableDeclaration => new + { + FieldName = variableDeclaration.Identifier.ValueText, + Invocation = (InvocationExpressionSyntax)variableDeclaration.Initializer.Value + }) + .Where(fieldNameAndInvocation => + fieldNameAndInvocation.Invocation.Expression.GetLastToken().ValueText == "Register" && + fieldNameAndInvocation.Invocation.ArgumentList.Arguments.Count > 0 && + fieldNameAndInvocation.Invocation.ArgumentList.Arguments[0].Expression.IsKind(SyntaxKind.StringLiteralExpression) && + fieldNameAndInvocation.Invocation.ArgumentList.Arguments[0].Expression.GetLastToken().ValueText is string propertyName && + fieldNameAndInvocation.FieldName.StartsWith(propertyName, StringComparison.Ordinal) && + fieldNameAndInvocation.FieldName.Length == propertyName.Length + "Property".Length && // Check that they are equal without creating temporary strings. + InstancePropertyWithPropertyNameExists(propertyName, fieldNameAndInvocation.Invocation) + && + // If we reach this point it means that we have a field declaration that in a real case most likely + // 99.9999 % percent sure represents a dependency property declaration. Cool :-) + // Still, we have to check for those 0.00001% since we could have a situation sketched + // in the smoke tests, where the Register method or the DependencyProperty class are not the "real" one. + // I am asking myself now if this level of paranoia is really appropriate considering the cost of + // this additional analysis. Hmmm. + // TODO-THINK: We can provide an analysis option like "Use optimistic analysis" that would skip the below test. + semanticModel.GetSymbolInfo(fieldNameAndInvocation.Invocation).Symbol is IMethodSymbol method && + method.ContainingType?.Name == "DependencyProperty" && + (method.ContainingType.ContainingType == null || method.ContainingType.ContainingType.IsNamespace) && // It must not be nested in another type. + method.ContainingType.ContainingNamespace.FullNameIsEqualTo("System.Windows") + // To be really sure, we should check here that the DependencyProperty type is + // really the System.Windows.DependencyProperty. And this check would add a whole + // bunch of super crazy paranoia on already paranoid check ;-) + // Basically, the only possibility for this check to fail would be if someone + // introduces it's own type named DependencyProperty that implicitly converts + // the System.Windows.DependencyProperty to itself. This is demonstrated in + // smoke tests but it is completely crazy. Who would ever do that? + // And since this check would be quite complex to implement, we will simply skip it. + ) + .Select(fieldNameAndInvocation => fieldNameAndInvocation.Invocation.ArgumentList.Arguments[0]) + .ToArray(); + + bool InstancePropertyWithPropertyNameExists(string propertyName, SyntaxNode anyChildNodeWithinTypeDeclaration) + { + var typeDeclaration = anyChildNodeWithinTypeDeclaration.FirstAncestorOrSelf(); + if (typeDeclaration == null) return false; + + // We could cache the information about non static properties per type declaration + // to avoid traversing the tree every time. + // But in the real world the number of dependency properties per type is very moderate. + // This would most likely be a premature optimization. + // So let's leave it this way. + return typeDeclaration + .DescendantNodes() + .OfType( + ) + .Any(property => + property.Modifiers.All(token => !token.IsKind(SyntaxKind.StaticKeyword)) && + property.Identifier.ValueText == propertyName + ); + } + } + } + } +} \ No newline at end of file diff --git a/tests/smoke/CSharp60/CSharp60.csproj b/tests/smoke/CSharp60/CSharp60.csproj index 43d698a..608c677 100644 --- a/tests/smoke/CSharp60/CSharp60.csproj +++ b/tests/smoke/CSharp60/CSharp60.csproj @@ -32,6 +32,8 @@ 4 + + @@ -40,6 +42,7 @@ + @@ -59,6 +62,10 @@ + + + + diff --git a/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression.cs b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression.cs new file mode 100644 index 0000000..e4204dd --- /dev/null +++ b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression.cs @@ -0,0 +1,128 @@ +// ReSharper disable All + +// Expected number of suggestions: 15 + +using System.Windows; +using static System.Windows.DependencyProperty; + +namespace CSharp60.NameofExpressions.UseNameofExpressionInDependencyPropertyDeclarations +{ + class DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression + { + public static readonly DependencyProperty StringProperty; + + public static readonly DependencyProperty DoubleProperty; + + public static readonly DependencyProperty FloatProperty; + + public static readonly DependencyProperty IntProperty; + + public static readonly DependencyProperty BooleanProperty; + + public static readonly DependencyProperty OtherStringProperty; + + public static readonly DependencyProperty OtherDoubleProperty; + + public static readonly DependencyProperty OtherFloatProperty; + + public static readonly DependencyProperty OtherIntProperty; + + public static readonly DependencyProperty OtherBooleanProperty; + + public static readonly System.Windows.DependencyProperty MoreStringProperty; + + public static readonly System.Windows.DependencyProperty MoreDoubleProperty; + + public static readonly System.Windows.DependencyProperty MoreFloatProperty; + + public static readonly System.Windows.DependencyProperty MoreIntProperty; + + public static readonly System.Windows.DependencyProperty MoreBooleanProperty; + + static DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression() + { + StringProperty = + DependencyProperty.Register("String", typeof(string), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression)); + + DoubleProperty = + DependencyProperty.Register("Double", typeof(double), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + FloatProperty = + DependencyProperty.Register("Float", typeof(float), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + IntProperty = + DependencyProperty.Register("Int", typeof(int), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + BooleanProperty = + DependencyProperty.Register("Boolean", typeof(bool), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + OtherStringProperty = + Register("OtherString", typeof(string), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression)); + + OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + OtherIntProperty = + Register("OtherInt", typeof(int), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression)); + + MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInConstructorThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + } + + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } +} \ No newline at end of file diff --git a/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression.cs b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression.cs new file mode 100644 index 0000000..0965039 --- /dev/null +++ b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression.cs @@ -0,0 +1,98 @@ +// ReSharper disable All + +// Expected number of suggestions: 15 + +using System.Windows; +using static System.Windows.DependencyProperty; + +namespace CSharp60.NameofExpressions.UseNameofExpressionInDependencyPropertyDeclarations +{ + class DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression + { + public static readonly DependencyProperty StringProperty = + DependencyProperty . Register ("String", typeof(string), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression)); + + public static readonly DependencyProperty DoubleProperty = + DependencyProperty. Register("Double", typeof(double), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + public static readonly DependencyProperty FloatProperty = + DependencyProperty.Register ("Float", typeof(float), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty IntProperty = + DependencyProperty . Register + ("Int", typeof(int), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly DependencyProperty OtherStringProperty = + Register("OtherString", typeof(string), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression)); + + public static readonly DependencyProperty OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + public static readonly DependencyProperty OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty OtherIntProperty = + Register("OtherInt", typeof(int), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly System.Windows.DependencyProperty MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression)); + + public static readonly System.Windows.DependencyProperty MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()); + + public static readonly System.Windows.DependencyProperty MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))); + + public static readonly System.Windows.DependencyProperty MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly System.Windows.DependencyProperty MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInFieldsDeclarationsThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } +} \ No newline at end of file diff --git a/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression.cs b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression.cs new file mode 100644 index 0000000..79027ef --- /dev/null +++ b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression.cs @@ -0,0 +1,102 @@ +// ReSharper disable All + +// Expected number of suggestions: 15 + +using System.Windows; +using static System.Windows.DependencyProperty; + +namespace CSharp60.NameofExpressions.UseNameofExpressionInDependencyPropertyDeclarations +{ + class DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression + { + public static readonly DependencyProperty + StringProperty = + DependencyProperty . Register ("String", typeof(string), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression)), + + DoubleProperty = + DependencyProperty.Register ("Double", typeof(double), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()), + + FloatProperty = + DependencyProperty. Register("Float", typeof(float), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))), + + IntProperty = + DependencyProperty . Register + ("Int", typeof(int), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)), + + BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + + public static readonly DependencyProperty + OtherStringProperty = + Register("OtherString", typeof(string), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression)), + + OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()), + + OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))), + + OtherIntProperty = + Register("OtherInt", typeof(int), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)), + + OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly System.Windows.DependencyProperty + MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression)), + + MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata()), + + MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(float))), + + MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)), + + MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(DependencyPropertyDeclarationsInSingleFieldDeclarationThatAreCandidatesToUseNameofExpression), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } +} \ No newline at end of file diff --git a/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsThatAreNotCandidatesToUseNameofExpression.cs b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsThatAreNotCandidatesToUseNameofExpression.cs new file mode 100644 index 0000000..b3453e9 --- /dev/null +++ b/tests/smoke/CSharp60/NameofExpressions/UseNameofExpressionInDependencyPropertyDeclarations/DependencyPropertyDeclarationsThatAreNotCandidatesToUseNameofExpression.cs @@ -0,0 +1,465 @@ +// ReSharper disable All + +using System; +using System.Windows; +using static System.Windows.DependencyProperty; + +namespace CSharp60.NameofExpressions.UseNameofExpressionInDependencyPropertyDeclarations +{ + class DependencyPropertyFieldNameDoesNotMachPropertyName + { + public static readonly DependencyProperty StringXProperty = + DependencyProperty . Register ("String", typeof(string), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName)); + + public static readonly DependencyProperty DoubleXProperty = + DependencyProperty. Register("Double", typeof(double), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata()); + + public static readonly DependencyProperty FloatXProperty = + DependencyProperty.Register ("Float", typeof(float), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty IntXProperty = + DependencyProperty . Register + ("Int", typeof(int), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty BooleanXProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly DependencyProperty OtherStringXProperty = + Register("OtherString", typeof(string), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName)); + + public static readonly DependencyProperty OtherDoubleXProperty = + Register("OtherDouble", typeof(double), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata()); + + public static readonly DependencyProperty OtherFloatXProperty = + Register("OtherFloat", typeof(float), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty OtherIntXProperty = + Register("OtherInt", typeof(int), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty OtherBooleanXProperty = + Register("OtherBoolean", typeof(bool), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly System.Windows.DependencyProperty MoreStringXProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName)); + + public static readonly System.Windows.DependencyProperty MoreDoubleXProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata()); + + public static readonly System.Windows.DependencyProperty MoreFloatXProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(float))); + + public static readonly System.Windows.DependencyProperty MoreIntXProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly System.Windows.DependencyProperty MoreBooleanXProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(DependencyPropertyFieldNameDoesNotMachPropertyName), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } + + class DependencyPropertyFieldsAreNotStaticAndReadonly + { + public static DependencyProperty StringProperty = + DependencyProperty.Register("String", typeof(string), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly)); + + public static DependencyProperty DoubleProperty = + DependencyProperty.Register("Double", typeof(double), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata()); + + public static DependencyProperty FloatProperty = + DependencyProperty.Register("Float", typeof(float), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(float))); + + public static DependencyProperty IntProperty = + DependencyProperty.Register + ("Int", typeof(int), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static DependencyProperty BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public readonly DependencyProperty OtherStringProperty = + Register("OtherString", typeof(string), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly)); + + public readonly DependencyProperty OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata()); + + public readonly DependencyProperty OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(float))); + + public readonly DependencyProperty OtherIntProperty = + Register("OtherInt", typeof(int), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public readonly DependencyProperty OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public System.Windows.DependencyProperty MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly)); + + public System.Windows.DependencyProperty MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata()); + + public System.Windows.DependencyProperty MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(float))); + + public System.Windows.DependencyProperty MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public System.Windows.DependencyProperty MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(DependencyPropertyFieldsAreNotStaticAndReadonly), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } + + class InstancePropertyWithPropertyNameDoesNotExist + { + public static readonly DependencyProperty StringProperty = + DependencyProperty.Register("String", typeof(string), typeof(InstancePropertyWithPropertyNameDoesNotExist)); + + public static readonly DependencyProperty DoubleProperty = + DependencyProperty.Register("Double", typeof(double), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata()); + + public static readonly DependencyProperty FloatProperty = + DependencyProperty.Register("Float", typeof(float), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty IntProperty = + DependencyProperty.Register + ("Int", typeof(int), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly DependencyProperty OtherStringProperty = + Register("OtherString", typeof(string), typeof(InstancePropertyWithPropertyNameDoesNotExist)); + + public static readonly DependencyProperty OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata()); + + public static readonly DependencyProperty OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty OtherIntProperty = + Register("OtherInt", typeof(int), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly System.Windows.DependencyProperty MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(InstancePropertyWithPropertyNameDoesNotExist)); + + public static readonly System.Windows.DependencyProperty MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata()); + + public static readonly System.Windows.DependencyProperty MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(float))); + + public static readonly System.Windows.DependencyProperty MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly System.Windows.DependencyProperty MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(InstancePropertyWithPropertyNameDoesNotExist), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string StringX { get; set; } + public double DoubleX { get; set; } + public float FloatX { get; set; } + public int IntX { get; set; } + public float BooleanX { get; set; } + public string OtherStringX { get; set; } + public double OtherDoubleX { get; set; } + public float OtherFloatX { get; set; } + public int OtherIntX { get; set; } + public float OtherBooleanX { get; set; } + public static string MoreString { get; set; } + public static double MoreDouble { get; set; } + public static float MoreFloat { get; set; } + public static int MoreInt { get; set; } + public static float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } + + class StaticPropertyFieldIsNotOfTypeDependencyProperty + { + public static readonly object StringProperty = + DependencyProperty.Register("String", typeof(string), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty)); + + public static readonly object DoubleProperty = + DependencyProperty.Register("Double", typeof(double), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata()); + + public static readonly object FloatProperty = + DependencyProperty.Register("Float", typeof(float), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(float))); + + public static readonly object IntProperty = + DependencyProperty.Register + ("Int", typeof(int), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly object BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly object OtherStringProperty = + Register("OtherString", typeof(string), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty)); + + public static readonly object OtherDoubleProperty = + Register("OtherDouble", typeof(double), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata()); + + public static readonly object OtherFloatProperty = + Register("OtherFloat", typeof(float), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(float))); + + public static readonly object OtherIntProperty = + Register("OtherInt", typeof(int), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly object OtherBooleanProperty = + Register("OtherBoolean", typeof(bool), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public static readonly System.Object MoreStringProperty = + DependencyProperty.Register("MoreString", typeof(string), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty)); + + public static readonly System.Object MoreDoubleProperty = + DependencyProperty.Register("MoreDouble", typeof(double), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata()); + + public static readonly System.Object MoreFloatProperty = + DependencyProperty.Register("MoreFloat", typeof(float), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(float))); + + public static readonly System.Object MoreIntProperty = + DependencyProperty.Register("MoreInt", typeof(int), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly System.Object MoreBooleanProperty = + DependencyProperty.Register("MoreBoolean", typeof(bool), typeof(StaticPropertyFieldIsNotOfTypeDependencyProperty), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + public string OtherString { get; set; } + public double OtherDouble { get; set; } + public float OtherFloat { get; set; } + public int OtherInt { get; set; } + public float OtherBoolean { get; set; } + public string MoreString { get; set; } + public double MoreDouble { get; set; } + public float MoreFloat { get; set; } + public int MoreInt { get; set; } + public float MoreBoolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } + + class RegisterMethodIsNotTheRealRegisterMethod + { + public class DependencyProperty + { + public static System.Windows.DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata = null) + { + return null; + } + } + + public static readonly System.Windows.DependencyProperty StringProperty = + DependencyProperty.Register("String", typeof(string), typeof(RegisterMethodIsNotTheRealRegisterMethod)); + + public static readonly System.Windows.DependencyProperty DoubleProperty = + DependencyProperty.Register("Double", typeof(double), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata()); + + public static readonly System.Windows.DependencyProperty FloatProperty = + DependencyProperty.Register("Float", typeof(float), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(float))); + + public static readonly System.Windows.DependencyProperty IntProperty = + DependencyProperty.Register + ("Int", typeof(int), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly System.Windows.DependencyProperty BooleanProperty = + DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } + + // This class will have 5 false positives. + // This is fine. We do not want to cover this case. + // See the explanantion given in the UseNameofExpressionInDependencyPropertyDeclarations. + class DependecyPropertyTypeIsNotTheRealDependencyPropertyType + { + public class DependencyProperty + { + public static implicit operator DependencyProperty(System.Windows.DependencyProperty dependencyProperty) + { + return null; + } + } + + public static readonly DependencyProperty StringProperty = + System.Windows.DependencyProperty.Register("String", typeof(string), typeof(RegisterMethodIsNotTheRealRegisterMethod)); + + public static readonly DependencyProperty DoubleProperty = + System.Windows.DependencyProperty.Register("Double", typeof(double), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata()); + + public static readonly DependencyProperty FloatProperty = + System.Windows.DependencyProperty.Register("Float", typeof(float), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(float))); + + public static readonly DependencyProperty IntProperty = + System.Windows.DependencyProperty.Register + ("Int", typeof(int), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(int), OnDependencyPropertyChanged)); + + public static readonly DependencyProperty BooleanProperty = + System.Windows.DependencyProperty + . + Register + ("Boolean", typeof(bool), typeof(RegisterMethodIsNotTheRealRegisterMethod), + new PropertyMetadata(default(bool), OnDependencyPropertyChanged, CoerceValueCallback)); + + public string String { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public int Int { get; set; } + public float Boolean { get; set; } + + public static void OnDependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + } + + private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue) + { + return null; + } + } +} \ No newline at end of file