Skip to content

Commit

Permalink
[GH-1] - more descriptive messages for csharp implementation, initial…
Browse files Browse the repository at this point in the history
… fixes for VB
  • Loading branch information
tpodolak committed Jun 16, 2018
1 parent 9806bd4 commit 1c3c766
Show file tree
Hide file tree
Showing 12 changed files with 489 additions and 103 deletions.
361 changes: 361 additions & 0 deletions src/NSubstitute.Analyzers.CSharp/Resources.Designer.cs

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions src/NSubstitute.Analyzers.CSharp/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -158,31 +158,31 @@
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteForPartsOfUsedForInterfaceMessageFormat" xml:space="preserve">
<value>Can only substitute for parts of classes, not interfaces or delegates.</value>
<value>Can only substitute for parts of classes, not interfaces or delegates.Use Substitute.For&lt;{0}&gt; instead of Substitute.ForPartsOf&lt;{0}&gt; here.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteForPartsOfUsedForInterfaceTitle" xml:space="preserve">
<value>Substitute.ForPartsOf used for interface.</value>
<comment>The title of the diagnostic.</comment>
</data>
<data name="SubstituteForWithoutAccessibleConstructorDescription" xml:space="preserve">
<value>Missing parameterless constructor.</value>
<value>Could not find accessible constructor.</value>
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteForWithoutAccessibleConstructorMessageFormat" xml:space="preserve">
<value>Missing parameterless constructor.</value>
<value>Could not find accessible constructor. Make sure that type {0} exposes public or protected constructors.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteForWithoutAccessibleConstructorTitle" xml:space="preserve">
<value>Missing parameterless constructor.</value>
<value>Could not find accessible constructor.</value>
<comment>The title of the diagnostic.</comment>
</data>
<data name="SubstituteForConstructorParametersMismatchDescription" xml:space="preserve">
<value>Constructor parameters count mismatch.</value>
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteForConstructorParametersMismatchMessageFormat" xml:space="preserve">
<value>Constructor parameters count mismatch.</value>
<value>Arguments count passed to {0} do not match the constructor arguments count for {1}. Check the {1} constructors and make sure you have passed the required arguments count.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteForConstructorParametersMismatchTitle" xml:space="preserve">
Expand All @@ -194,19 +194,19 @@
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteForInternalMemberMessageFormat" xml:space="preserve">
<value>Substitute for internal member.</value>
<value>Can not substitute for internal type. To substitute for internal type expose your type to DynamicProxyGenAssembly2 via [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteForInternalMemberTitle" xml:space="preserve">
<value>Substitute for internal member.</value>
<value>Can not create.</value>
<comment>The title of the diagnostic.</comment>
</data>
<data name="SubstituteConstructorMismatchDescription" xml:space="preserve">
<value>Unable to find matching constructor.</value>
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteConstructorMismatchMessageFormat" xml:space="preserve">
<value>Unable to find matching constructor.</value>
<value>Arguments passed to {0} do not match the constructor arguments for {1}. Check the {1} constructors and make sure you have passed the required arguments and argument types.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteConstructorMismatchMemberTitle" xml:space="preserve">
Expand All @@ -230,7 +230,7 @@
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteConstructorArgumentsForInterfaceMessageFormat" xml:space="preserve">
<value>Can not provide constructor arguments when substituting for an interface.</value>
<value>Can not provide constructor arguments when substituting for an interface. Use Substitute.For&lt;{0}&gt;() instead.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteConstructorArgumentsForInterfaceMemberTitle" xml:space="preserve">
Expand All @@ -242,7 +242,7 @@
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="SubstituteConstructorArgumentsForDelegateMessageFormat" xml:space="preserve">
<value>Can not provide constructor arguments when substituting for a delegate.</value>
<value>Can not provide constructor arguments when substituting for a delegate. Use Substitute.For&lt;{0}&gt;() instead.</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="SubstituteConstructorArgumentsForDelegateMemberTitle" xml:space="preserve">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ private bool AnalyzeConstructorParametersCount(SubstituteContext<TInvocationExpr
case TypeKind.Interface when invocationArgumentTypes > 0:
var diagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteConstructorArgumentsForInterface,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
constructorContext.ConstructorType.ToString());

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);
return true;
Expand All @@ -197,7 +198,8 @@ private bool AnalyzeConstructorParametersCount(SubstituteContext<TInvocationExpr
case TypeKind.Delegate when invocationArgumentTypes > 0:
var delegateDiagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteConstructorArgumentsForDelegate,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
constructorContext.ConstructorType.ToString());

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(delegateDiagnostic);
return true;
Expand All @@ -207,9 +209,13 @@ private bool AnalyzeConstructorParametersCount(SubstituteContext<TInvocationExpr

if (constructorContext.PossibleConstructors != null && constructorContext.PossibleConstructors.Any() == false)
{
var symbol = substituteContext.SyntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(substituteContext.InvocationExpression);
var symbol2 = substituteContext.SyntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(substituteContext.InvocationExpression.DescendantNodes().First());
var diagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteForConstructorParametersMismatch,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
symbol.Symbol.ToSimplifiedMethodString(),
constructorContext.ConstructorType);

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);
return true;
Expand All @@ -224,7 +230,8 @@ private bool AnalyzeTypeKind(SubstituteContext<TInvocationExpressionSyntax> subs
{
var diagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteForPartsOfUsedForInterface,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
proxyType.ToString());

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);
return true;
Expand Down Expand Up @@ -260,9 +267,13 @@ private bool AnalyzeConstructorInvocation(SubstituteContext<TInvocationExpressio
substituteContext.SyntaxNodeAnalysisContext.SemanticModel.Compilation, ctor, constructorContext.InvocationParameters) ==
false))
{
var symbol = substituteContext.SyntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(substituteContext.InvocationExpression);
var x = symbol.Symbol.ToMinimalDisplayString(substituteContext.SyntaxNodeAnalysisContext.SemanticModel, 10, SymbolDisplayFormat.CSharpErrorMessageFormat);
var diagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteConstructorMismatch,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
symbol.Symbol.ToSimplifiedMethodString(),
constructorContext.ConstructorType.ToString());

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);
return true;
Expand All @@ -277,7 +288,8 @@ private bool AnalyzeConstructorAccessability(SubstituteContext<TInvocationExpres
{
var diagnostic = Diagnostic.Create(
DiagnosticDescriptorsProvider.SubstituteForWithoutAccessibleConstructor,
substituteContext.InvocationExpression.GetLocation());
substituteContext.InvocationExpression.GetLocation(),
constructorContext.ConstructorType.ToString());

substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic);
return true;
Expand Down
13 changes: 13 additions & 0 deletions src/NSubstitute.Analyzers.Shared/Extensions/ISymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,18 @@ public static bool InternalsVisibleToProxyGenerator(this ISymbol typeSymbol)
internalsVisibleToAttribute.ConstructorArguments.Any(arg =>
arg.Value.ToString() == MetadataNames.CastleDynamicProxyGenAssembly2Name);
}

public static string ToSimplifiedMethodString(this ISymbol symbol)
{
if (symbol == null)
{
return string.Empty;
}

// consider using span
var defaultString = symbol.ToString();
var bracketIndex = defaultString.IndexOf('(');
return bracketIndex > -1 ? defaultString.Substring(0, bracketIndex) : defaultString;
}
}
}
Loading

0 comments on commit 1c3c766

Please sign in to comment.