private ITypeSymbol[] GetArgumentTypeInfo(SubstituteContext <TInvocationExpression> substituteContext, TArgumentSyntax arrayArgument) { var typeInfo = GetTypeInfo(substituteContext, arrayArgument.DescendantNodes().First()); if (typeInfo.ConvertedType != null && typeInfo.ConvertedType.TypeKind == TypeKind.Array && typeInfo.Type == null) { return(null); } // new object[] { }; // means we dont pass any arguments var parameterExpressionsFromArrayArgument = GetParameterExpressionsFromArrayArgument(arrayArgument); if (parameterExpressionsFromArrayArgument == null) { return(null); } // new object[] { 1, 2, 3}); // means we pass arguments var types = parameterExpressionsFromArrayArgument .Select(exp => GetTypeInfo(substituteContext, exp).Type) .ToArray(); return(types); }
private void AnalyzePartialSubstitute(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { if (AnalyzeProxies(substituteContext)) { return; } var proxyType = _substituteProxyAnalysis.GetActualProxyTypeSymbol(substituteContext); if (proxyType == null) { return; } if (AnalyzeTypeKind(substituteContext, proxyType)) { return; } if (AnalyzeTypeAccessability(substituteContext, proxyType)) { return; } if (proxyType.TypeKind != TypeKind.Class) { return; } var constructorContext = _substituteConstructorAnalysis.CollectConstructorContext(substituteContext, proxyType); AnalyzeConstructor(substituteContext, constructorContext); }
private bool AnalyzeConstructorInvocation(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ConstructorContext constructorContext) { if (constructorContext.ConstructorType.TypeKind != TypeKind.Class || constructorContext.InvocationParameters == null || constructorContext.PossibleConstructors == null) { return(false); } if (constructorContext.PossibleConstructors.All(ctor => SubstituteConstructorMatcher.MatchesInvocation( 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(), symbol.Symbol.ToMinimalMethodString(substituteContext.SyntaxNodeAnalysisContext.SemanticModel), constructorContext.ConstructorType.ToString()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private void AnalyzeSubstituteForPartsOf(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { var proxyType = substituteContext.MethodSymbol.TypeArguments.FirstOrDefault(); if (proxyType == null) { return; } if (AnalyzeTypeKind(substituteContext, proxyType)) { return; } if (AnalyzeTypeAccessability(substituteContext, proxyType)) { return; } if (proxyType.TypeKind != TypeKind.Class) { return; } var constructorContext = SubstituteConstructorAnalysis.CollectConstructorContext(substituteContext, proxyType); AnalyzeConstructor(substituteContext, constructorContext); }
private ITypeSymbol[] GetGenericInvocationArgumentTypes(SubstituteContext <TInvocationExpression> substituteContext) { var arguments = GetInvocationArguments(substituteContext.InvocationExpression); if (arguments == null) { return(null); } if (arguments.Count == 0) { return(Array.Empty <ITypeSymbol>()); } var typeInfos = arguments.Select(arg => GetTypeInfo(substituteContext, arg.DescendantNodes().First())) .ToList(); var possibleParamsArgument = typeInfos.First(); // if passing array of objects as a sole element if (arguments.Count == 1 && possibleParamsArgument.ConvertedType is IArrayTypeSymbol arrayTypeSymbol && arrayTypeSymbol.ElementType.Equals(substituteContext.SyntaxNodeAnalysisContext.Compilation.ObjectType)) { return(GetArgumentTypeInfo(substituteContext, arguments.First())); } return(typeInfos.Select(type => type.Type).ToArray()); }
private ITypeSymbol[] GetInvocationInfo(SubstituteContext <TInvocationExpression> substituteContext) { var infos = substituteContext.MethodSymbol.IsGenericMethod ? GetGenericInvocationArgumentTypes(substituteContext) : GetNonGenericInvocationArgumentTypes(substituteContext); return(infos); }
public ITypeSymbol GetActualProxyTypeSymbol(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { var proxies = GetProxySymbols(substituteContext).ToList(); var classSymbol = proxies.FirstOrDefault(symbol => symbol.TypeKind == TypeKind.Class); return(classSymbol ?? proxies.FirstOrDefault()); }
private ITypeSymbol[] GetNonGenericInvocationArgumentTypes(SubstituteContext <TInvocationExpression> substituteContext) { // Substitute.For(new [] { typeof(T) }, new object[] { 1, 2, 3}) // actual arguments reside in second arg var arrayArgument = GetInvocationArguments(substituteContext.InvocationExpression)?.Skip(1).FirstOrDefault(); if (arrayArgument == null) { return(null); } return(GetArgumentTypeInfo(substituteContext, arrayArgument)); }
private bool AnalyzeTypeAccessability(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ITypeSymbol proxyType) { if (proxyType.DeclaredAccessibility == Accessibility.Internal && proxyType.InternalsVisibleToProxyGenerator() == false) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteForInternalMember, substituteContext.InvocationExpression.GetLocation()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private bool AnalyzeTypeKind(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ITypeSymbol proxyType) { if (proxyType.TypeKind == TypeKind.Interface || proxyType.TypeKind == TypeKind.Delegate) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteForPartsOfUsedForInterface, substituteContext.InvocationExpression.GetLocation(), proxyType.ToString()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private bool AnalyzeConstructorAccessibility(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ConstructorContext constructorContext) { if (constructorContext.ConstructorType.TypeKind == TypeKind.Class && constructorContext.AccessibleConstructors != null && constructorContext.AccessibleConstructors.Any() == false) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteForWithoutAccessibleConstructor, substituteContext.InvocationExpression.GetLocation(), constructorContext.ConstructorType.ToString()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private bool AnalyzeTypeKind(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ITypeSymbol proxyType) { if (proxyType.TypeKind == TypeKind.Interface || proxyType.TypeKind == TypeKind.Delegate) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.PartialSubstituteForUnsupportedType, substituteContext.InvocationExpression.GetLocation(), GetCorrespondingSubstituteMethod(substituteContext.InvocationExpression, substituteContext.MethodSymbol), substituteContext.InvocationExpression.ToString()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private bool AnalyzeConstructorParametersCount(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ConstructorContext constructorContext) { var invocationArgumentTypes = constructorContext.InvocationParameters?.Length; switch (constructorContext.ConstructorType.TypeKind) { case TypeKind.Interface when invocationArgumentTypes > 0: var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteConstructorArgumentsForInterface, substituteContext.InvocationExpression.GetLocation(), GetSubstituteMethodWithoutConstructorArguments(substituteContext.InvocationExpression, substituteContext.MethodSymbol)); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); case TypeKind.Interface: return(false); case TypeKind.Delegate when invocationArgumentTypes > 0: var delegateDiagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteConstructorArgumentsForDelegate, substituteContext.InvocationExpression.GetLocation(), GetSubstituteMethodWithoutConstructorArguments(substituteContext.InvocationExpression, substituteContext.MethodSymbol)); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(delegateDiagnostic); return(true); case TypeKind.Delegate: return(false); } if (constructorContext.PossibleConstructors != null && constructorContext.PossibleConstructors.Any() == false) { var symbol = substituteContext.SyntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(substituteContext.InvocationExpression); var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteForConstructorParametersMismatch, substituteContext.InvocationExpression.GetLocation(), symbol.Symbol.ToMinimalMethodString(substituteContext.SyntaxNodeAnalysisContext.SemanticModel), constructorContext.ConstructorType); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private bool AnalyzeProxies(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { var proxies = _substituteProxyAnalysis.GetProxySymbols(substituteContext).ToList(); var classProxies = proxies.Where(proxy => proxy.TypeKind == TypeKind.Class).Distinct(); if (classProxies.Count() > 1) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.SubstituteMultipleClasses, substituteContext.InvocationExpression.GetLocation()); substituteContext.SyntaxNodeAnalysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private void AnalyzeConstructor(SubstituteContext <TInvocationExpressionSyntax> substituteContext, ConstructorContext constructorContext) { if (AnalyzeConstructorAccessibility(substituteContext, constructorContext)) { return; } if (AnalyzeConstructorParametersCount(substituteContext, constructorContext)) { return; } if (AnalyzeConstructorInvocation(substituteContext, constructorContext)) { return; } }
public ConstructorContext CollectConstructorContext(SubstituteContext <TInvocationExpression> substituteContext, ITypeSymbol proxyTypeSymbol) { if (proxyTypeSymbol.Kind == SymbolKind.TypeParameter) { return(new ConstructorContext(proxyTypeSymbol, null, null, null)); } var accessibleConstructors = GetAccessibleConstructors(proxyTypeSymbol); var invocationParameterTypes = GetInvocationInfo(substituteContext); var possibleConstructors = invocationParameterTypes != null && accessibleConstructors != null ? accessibleConstructors.Where(ctor => ctor.Parameters.Length == invocationParameterTypes.Length) .ToArray() : null; return(new ConstructorContext( proxyTypeSymbol, accessibleConstructors, possibleConstructors, invocationParameterTypes)); }
private void AnalyzeSubstituteForMethod(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { if (AnalyzeProxies(substituteContext)) { return; } var proxyType = SubstituteProxyAnalysis.GetActualProxyTypeSymbol(substituteContext); if (proxyType == null) { return; } if (AnalyzeTypeAccessability(substituteContext, proxyType)) { return; } var constructorContext = SubstituteConstructorAnalysis.CollectConstructorContext(substituteContext, proxyType); AnalyzeConstructor(substituteContext, constructorContext); }
private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) { var invocationExpression = (TInvocationExpressionSyntax)syntaxNodeContext.Node; var methodSymbolInfo = syntaxNodeContext.SemanticModel.GetSymbolInfo(invocationExpression); if (methodSymbolInfo.Symbol?.Kind != SymbolKind.Method) { return; } var methodSymbol = (IMethodSymbol)methodSymbolInfo.Symbol; if (methodSymbol == null || methodSymbol.MethodKind != MethodKind.Ordinary) { return; } if (methodSymbol.IsSubstituteCreateLikeMethod() == false) { return; } var substituteContext = new SubstituteContext <TInvocationExpressionSyntax>(syntaxNodeContext, invocationExpression, methodSymbol); if (methodSymbol.Name.Equals(MetadataNames.NSubstituteForMethod, StringComparison.Ordinal) || methodSymbol.Name.Equals(MetadataNames.SubstituteFactoryCreate, StringComparison.Ordinal)) { AnalyzeSubstitute(substituteContext); return; } if (methodSymbol.Name.Equals(MetadataNames.NSubstituteForPartsOfMethod, StringComparison.Ordinal) || methodSymbol.Name.Equals(MetadataNames.SubstituteFactoryCreatePartial, StringComparison.Ordinal)) { AnalyzePartialSubstitute(substituteContext); } }
public ImmutableArray <ITypeSymbol> GetProxySymbols(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { if (substituteContext.MethodSymbol.IsGenericMethod) { return(substituteContext.MethodSymbol.TypeArguments); } var arrayParameters = GetArrayInitializerArguments(substituteContext.InvocationExpression)?.ToList(); if (arrayParameters == null) { return(ImmutableArray <ITypeSymbol> .Empty); } var proxyTypes = GetTypeOfLikeExpressions(arrayParameters) .Select(exp => substituteContext.SyntaxNodeAnalysisContext.SemanticModel .GetTypeInfo(exp.DescendantNodes().First())) .Where(model => model.Type != null) .Select(model => model.Type) .ToImmutableArray(); return(arrayParameters.Count == proxyTypes.Length ? proxyTypes : ImmutableArray <ITypeSymbol> .Empty); }
public ImmutableArray <ITypeSymbol> GetProxySymbols(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { return(GetProxySymbols(substituteContext.SyntaxNodeAnalysisContext.SemanticModel, substituteContext.InvocationExpression, substituteContext.MethodSymbol)); }
public ITypeSymbol GetActualProxyTypeSymbol(SubstituteContext <TInvocationExpressionSyntax> substituteContext) { return(GetActualProxyTypeSymbol(substituteContext.SyntaxNodeAnalysisContext.SemanticModel, substituteContext.InvocationExpression, substituteContext.MethodSymbol)); }
private TypeInfo GetTypeInfo(SubstituteContext <TInvocationExpression> substituteContext, SyntaxNode syntax) { return(substituteContext.SyntaxNodeAnalysisContext.SemanticModel.GetTypeInfo(syntax)); }