/// <summary> /// Make a generic type from arguments. /// </summary> /// <param name="baseType">The base type.</param> /// <param name="arguments">The arguments.</param> /// <returns>The generic type.</returns> public static INamedTypeSymbol MakeGeneric(this INamedTypeSymbol baseType, TypedConstant arguments) { if (arguments.Values.Length > 0) { return(baseType.Construct(arguments.Values.Select(v => v.Value).Cast <INamedTypeSymbol>().ToArray())); } if (arguments.Value is INamedTypeSymbol arg) { return(baseType.Construct(arg)); } return(null); }
private SyntaxNode FixMethod( bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method, ITypeSymbol taskType, INamedTypeSymbol taskOfTType) { var newReturnType = method.ReturnType; if (methodSymbol.ReturnsVoid) { if (!keepVoid) { newReturnType = taskType.GenerateTypeSyntax(); } } else { if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType)) { // If it's not already Task-like, then wrap the existing return type // in Task<>. newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax(); } } var newModifiers = method.Modifiers.Add(s_asyncToken); return method.WithReturnType(newReturnType).WithModifiers(newModifiers); }
private SyntaxNode FixMethod( bool keepVoid, IMethodSymbol methodSymbol, MethodDeclarationSyntax method, INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType) { var newReturnType = method.ReturnType; if (methodSymbol.ReturnsVoid) { if (!keepVoid) { newReturnType = taskType.GenerateTypeSyntax(); } } else { if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType, valueTaskOfTType)) { // If it's not already Task-like, then wrap the existing return type // in Task<>. newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax(); } } var newModifiers = method.Modifiers.Add(s_asyncToken); return(method.WithReturnType(newReturnType).WithModifiers(newModifiers)); }
private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType) { var namedType = context.Symbol as INamedTypeSymbol; if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class)) { return; } bool overridesObjectEquals = namedType.OverridesEquals(); INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType); INamedTypeSymbol implementation = namedType .Interfaces .Where(x => x.Equals(constructedEquatable)) .FirstOrDefault(); bool implementsEquatable = implementation != null; if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct) { context.ReportDiagnostic(namedType.CreateDiagnostic(s_implementIEquatableDescriptor, namedType)); } if (!overridesObjectEquals && implementsEquatable) { context.ReportDiagnostic(namedType.CreateDiagnostic(s_overridesObjectEqualsDescriptor, namedType)); } }
private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType) { var namedType = context.Symbol as INamedTypeSymbol; if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class)) { return; } var methodSymbol = namedType .GetMembers("Equals") .OfType <IMethodSymbol>() .Where(m => IsObjectEqualsOverride(m, objectType)) .FirstOrDefault(); var overridesObjectEquals = methodSymbol != null; var constructedEquatable = equatableType.Construct(namedType); var implementation = namedType .Interfaces .Where(x => x.Equals(constructedEquatable)) .FirstOrDefault(); var implementsEquatable = implementation != null; if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct) { context.ReportDiagnostic(Diagnostic.Create(s_implementIEquatableDescriptor, methodSymbol.Locations[0], namedType)); } if (!overridesObjectEquals && implementsEquatable) { context.ReportDiagnostic(Diagnostic.Create(s_overridesObjectEqualsDescriptor, namedType.Locations[0], namedType)); } }
private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol equatableType) { var namedType = context.Symbol as INamedTypeSymbol; if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class)) { return; } bool overridesObjectEquals = namedType.OverridesEquals(); INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType); INamedTypeSymbol implementation = namedType .Interfaces .Where(x => x.Equals(constructedEquatable)) .FirstOrDefault(); bool implementsEquatable = implementation != null; if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct) { context.ReportDiagnostic(namedType.CreateDiagnostic(s_implementIEquatableDescriptor, namedType)); } if (!overridesObjectEquals && implementsEquatable) { context.ReportDiagnostic(namedType.CreateDiagnostic(s_overridesObjectEqualsDescriptor, namedType)); } }
private static TypeSyntax FixMethodReturnType( bool keepVoid, IMethodSymbol methodSymbol, TypeSyntax returnType, INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType) { var newReturnType = returnType; if (methodSymbol.ReturnsVoid) { if (!keepVoid) { newReturnType = taskType.GenerateTypeSyntax(); } } else { if (!IsTaskLike(methodSymbol.ReturnType, taskType, taskOfTType, valueTaskOfTType)) { // If it's not already Task-like, then wrap the existing return type // in Task<>. newReturnType = taskOfTType.Construct(methodSymbol.ReturnType).GenerateTypeSyntax(); } } return(newReturnType.WithTriviaFrom(returnType)); }
public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol?typeArgument, [NotNullWhen(returnValue: true)] INamedTypeSymbol?interfaceType, string interfaceMethodName) { INamedTypeSymbol?constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType; return(constructedInterface?.GetMembers(interfaceMethodName).FirstOrDefault() is IMethodSymbol interfaceMethod && SymbolEqualityComparer.Default.Equals(method, method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod))); }
public static INamedTypeSymbol Construct( this INamedTypeSymbol definition, params TypeSymbol[] typeArguments ) { return(definition.Construct(typeArguments.Select(s => s.GetPublicSymbol()).ToArray())); }
private static bool TryGetGenericType( Compilation compilation, INamedTypeSymbol genericTypeDefinition, ImmutableArray <string> genericTypeArguments, out INamedTypeSymbol genericType ) { INamedTypeSymbol[] genericTypeArgumentSymbols = new INamedTypeSymbol[genericTypeArguments.Length]; for (int i = 0; i < genericTypeArguments.Length; i++) { string genericTypeArgumentName = genericTypeArguments[i]; INamedTypeSymbol genericTypeArgumentSymbol = compilation.GetTypeByMetadataName(genericTypeArgumentName); if (genericTypeArgumentSymbol.IsNullOrErrorType()) { genericType = null; return(false); } genericTypeArgumentSymbols[i] = genericTypeArgumentSymbol; } genericType = genericTypeDefinition.Construct(genericTypeArgumentSymbols); if (genericType.IsNullOrErrorType()) { genericType = null; return(false); } return(true); }
private static async Task <Document> ImplementEquatableInStructAsync(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, Compilation compilation, INamedTypeSymbol equatableType, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var generator = editor.Generator; var equalsMethod = generator.MethodDeclaration( WellKnownMemberNames.ObjectEquals, new[] { generator.ParameterDeclaration("other", generator.TypeExpression(typeSymbol)) }, returnType: generator.TypeExpression(SpecialType.System_Boolean), accessibility: Accessibility.Public, statements: generator.DefaultMethodBody(compilation)); editor.AddMember(declaration, equalsMethod); INamedTypeSymbol constructedType = equatableType.Construct(typeSymbol); editor.AddInterfaceType(declaration, generator.TypeExpression(constructedType)); return(editor.GetChangedDocument()); }
private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType) { var namedType = context.Symbol as INamedTypeSymbol; if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class)) { return; } var methodSymbol = namedType .GetMembers("Equals") .OfType<IMethodSymbol>() .Where(m => IsObjectEqualsOverride(m, objectType)) .FirstOrDefault(); var overridesObjectEquals = methodSymbol != null; var constructedEquatable = equatableType.Construct(namedType); var implementation = namedType .Interfaces .Where(x => x.Equals(constructedEquatable)) .FirstOrDefault(); var implementsEquatable = implementation != null; if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct) { context.ReportDiagnostic(Diagnostic.Create(s_implementIEquatableDescriptor, methodSymbol.Locations[0], namedType)); } if (!overridesObjectEquals && implementsEquatable) { context.ReportDiagnostic(Diagnostic.Create(s_overridesObjectEqualsDescriptor, namedType.Locations[0], namedType)); } }
private static ITypeSymbol GetMemberNewType( ISymbol memberSymbol, ITypeSymbol memberTypeSymbol, ExpressionSyntax expression, ITypeSymbol expressionSymbol, SemanticModel semanticModel, CancellationToken cancellationToken) { if (memberSymbol.IsAsyncMethod()) { if (expression.IsKind(SyntaxKind.AwaitExpression)) { var awaitExpression = (AwaitExpressionSyntax)expression; if (awaitExpression.Expression != null) { var awaitableSymbol = semanticModel.GetTypeSymbol(awaitExpression.Expression, cancellationToken) as INamedTypeSymbol; if (awaitableSymbol != null) { INamedTypeSymbol taskOfTSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T); if (awaitableSymbol.ConstructedFrom.Equals(taskOfTSymbol)) { return(awaitableSymbol); } } } } else if (memberTypeSymbol.IsNamedType()) { INamedTypeSymbol taskOfTSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T); if (((INamedTypeSymbol)memberTypeSymbol).ConstructedFrom.Equals(taskOfTSymbol)) { if (expressionSymbol.IsNamedType() && ((INamedTypeSymbol)expressionSymbol).ConstructedFrom.Equals(taskOfTSymbol)) { return(null); } INamedTypeSymbol taskSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task); if (expressionSymbol.Equals(taskSymbol)) { return(null); } return(taskOfTSymbol.Construct(expressionSymbol)); } } } else { return(expressionSymbol); } return(null); }
/// <summary> /// Checks if the given method is an implementation of the given interface method /// Substituted with the given typeargument. /// </summary> public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol typeArgument, INamedTypeSymbol interfaceType, string interfaceMethodName) { INamedTypeSymbol constructedInterface = typeArgument != null?interfaceType?.Construct(typeArgument) : interfaceType; var interfaceMethod = constructedInterface?.GetMembers(interfaceMethodName).Single() as IMethodSymbol; return(interfaceMethod != null && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod))); }
public static async Task ComputeRefactoringAsync(RefactoringContext context, StructDeclarationSyntax structDeclaration) { SyntaxToken identifier = structDeclaration.Identifier; if (identifier.IsMissing) { return; } TextSpan span = identifier.Span; BaseListSyntax baseList = structDeclaration.BaseList; if (baseList != null) { span = TextSpan.FromBounds(span.Start, baseList.Span.End); } TypeParameterListSyntax typeParameterList = structDeclaration.TypeParameterList; if (typeParameterList != null) { span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End); } if (!span.Contains(context.Span)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(structDeclaration, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { return; } INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_IEquatable_T); if (equatableSymbol == null) { return; } equatableSymbol = equatableSymbol.Construct(typeSymbol); if (typeSymbol.Implements(equatableSymbol, allInterfaces: true)) { return; } context.RegisterRefactoring( GetTitle(equatableSymbol, semanticModel, structDeclaration.SpanStart), f => RefactorAsync(context.Document, structDeclaration, typeSymbol, equatableSymbol, semanticModel, f), RefactoringIdentifiers.ImplementIEquatableOfT); }
private static bool TypeImplementsEquatable(INamedTypeSymbol type, INamedTypeSymbol equatableType) { INamedTypeSymbol constructedEquatable = equatableType.Construct(type); INamedTypeSymbol implementation = type .Interfaces .FirstOrDefault(x => x.Equals(constructedEquatable)); return(implementation != null); }
private static bool ImplementsIEquatable(ITypeSymbol memberType, INamedTypeSymbol iequatableType) { if (iequatableType != null) { var constructed = iequatableType.Construct(memberType); return(memberType.AllInterfaces.Contains(constructed)); } return(false); }
private static Maybe <Case.ClassCase> CreateClassCase( INamedTypeSymbol doClassSymbol, INamedTypeSymbol subClassSymbol) { var containingType = subClassSymbol.ContainingType; var openDoClassSymbol = doClassSymbol.IsGenericType ? doClassSymbol.ConstructedFrom : doClassSymbol; if (containingType == null) { if (subClassSymbol.TypeParameters.Length != doClassSymbol.TypeParameters.Length) { return(Maybe.NoValue); } var baseTypeOfSubClass = subClassSymbol.BaseType; if (baseTypeOfSubClass.IsGenericType && baseTypeOfSubClass.TypeArguments.Any(x => x.Kind != SymbolKind.TypeParameter)) { return(Maybe.NoValue); } if (!doClassSymbol.IsGenericType || doClassSymbol.IsUnboundGenericType) { return(new Case.ClassCase(subClassSymbol)); } return(new Case.ClassCase(subClassSymbol.Construct(doClassSymbol.TypeArguments.ToArray()))); } if (containingType.Equals(openDoClassSymbol)) { if (HasTypeParameters(subClassSymbol)) { return(Maybe.NoValue); } if (!openDoClassSymbol.IsGenericType || openDoClassSymbol.IsUnboundGenericType) { return(new Case.ClassCase(subClassSymbol)); } var namedTypeSymbol = doClassSymbol.GetMembers() .OfType <INamedTypeSymbol>().Single(x => x.OriginalDefinition.Equals(subClassSymbol)); return(new Case.ClassCase( namedTypeSymbol)); } return(Maybe.NoValue); }
private static SyntaxNode GetReturnStatementForExplicitClass(SyntaxGenerator generator, INamedTypeSymbol typeSymbol, SyntaxNode argumentName, INamedTypeSymbol equatableType) { return(generator.ReturnStatement( generator.InvocationExpression( generator.MemberAccessExpression( generator.CastExpression( equatableType.Construct(typeSymbol), generator.ThisExpression()), WellKnownMemberNames.ObjectEquals), generator.TryCastExpression( argumentName, typeSymbol)))); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out SyntaxNode node, predicate: f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement))) { return; } Diagnostic diagnostic = context.Diagnostics[0]; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(node, context.CancellationToken); Debug.Assert(methodSymbol != null, node.Kind().ToString()); ITypeSymbol typeSymbol = methodSymbol.ReturnType; if (typeSymbol.IsErrorType()) { return; } (bool containsReturnAwait, bool containsAwaitStatement) = AnalyzeAwaitExpressions(node); Debug.Assert(containsAwaitStatement || containsReturnAwait, node.ToString()); if (containsAwaitStatement) { INamedTypeSymbol taskSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task); CodeFixRegistrator.ChangeReturnType(context, diagnostic, node, taskSymbol, semanticModel, "Task"); } if (containsReturnAwait) { INamedTypeSymbol taskOfT = semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task_T); typeSymbol = taskOfT.Construct(typeSymbol); CodeFixRegistrator.ChangeReturnType(context, diagnostic, node, typeSymbol, semanticModel, "TaskOfT"); } }
public static async Task ComputeRefactoringAsync(RefactoringContext context, ClassDeclarationSyntax classDeclaration) { SyntaxToken identifier = classDeclaration.Identifier; if (!identifier.IsMissing) { TextSpan span = identifier.Span; BaseListSyntax baseList = classDeclaration.BaseList; if (baseList != null) { span = TextSpan.FromBounds(span.Start, baseList.Span.End); } TypeParameterListSyntax typeParameterList = classDeclaration.TypeParameterList; if (typeParameterList != null) { span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End); } if (span.Contains(context.Span)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); INamedTypeSymbol classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken); if (classSymbol?.IsErrorType() == false && !classSymbol.IsStatic) { INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_IEquatable_T); if (equatableSymbol != null) { equatableSymbol = equatableSymbol.Construct(classSymbol); if (!classSymbol.Implements(equatableSymbol)) { context.RegisterRefactoring( GetTitle(equatableSymbol, semanticModel, classDeclaration.SpanStart), f => RefactorAsync(context.Document, classDeclaration, classSymbol, equatableSymbol, semanticModel, f)); } } } } } }
protected override SyntaxNode AddAsyncKeywordAndTaskReturnType(SyntaxNode node, ITypeSymbol existingReturnType, INamedTypeSymbol taskTypeSymbol) { var methodNode = node as MethodDeclarationSyntax; if (methodNode == null) { return(null); } if (taskTypeSymbol == null) { return(null); } var returnType = taskTypeSymbol.Construct(existingReturnType).GenerateTypeSyntax(); return(AddAsyncKeyword(methodNode.WithReturnType(returnType))); }
private static bool HasExplicitEqualsImplementation(INamedTypeSymbol typeSymbol, INamedTypeSymbol equatableType) { INamedTypeSymbol constructedType = equatableType.Construct(typeSymbol); IMethodSymbol constructedEqualsMethod = constructedType.GetMembers().OfType <IMethodSymbol>().Single(); foreach (IMethodSymbol method in typeSymbol.GetMembers().OfType <IMethodSymbol>()) { foreach (IMethodSymbol explicitImplementation in method.ExplicitInterfaceImplementations) { if (explicitImplementation.Equals(constructedEqualsMethod)) { return(true); } } } return(false); }
private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol equatableType) { if (!(context.Symbol is INamedTypeSymbol namedType) || (namedType.TypeKind != TypeKind.Struct && namedType.TypeKind != TypeKind.Class) || (namedType.TypeKind == TypeKind.Struct && namedType.IsRefLikeType)) { return; } bool overridesObjectEquals = namedType.OverridesEquals(); INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType); INamedTypeSymbol implementation = namedType .AllInterfaces .FirstOrDefault(x => x.Equals(constructedEquatable)); bool implementsEquatable = implementation != null; if (implementsEquatable) { // Bail out for following cases: // 1. There is no method implementing IEquatable.Equals method, indicating compiler error. // 2. Base type is implementing the IEquatable for this type, and hence is responsible for overriding object Equals. // For example, we should not flag type B below as IEquatable<B> is implemented by its base type: // class B : A<B> { } // class A<T> : IEquatable<T> // where T: A<T> // { ... } if (!(constructedEquatable.GetMembers("Equals").FirstOrDefault() is IMethodSymbol equatableEqualsMethod) || !Equals(namedType, namedType.FindImplementationForInterfaceMember(equatableEqualsMethod)?.ContainingType)) { return; } } if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct) { context.ReportDiagnostic(namedType.CreateDiagnostic(ImplementIEquatableDescriptor, namedType)); } if (!overridesObjectEquals && implementsEquatable) { context.ReportDiagnostic(namedType.CreateDiagnostic(OverridesObjectEqualsDescriptor, namedType)); } }
public static INamedTypeSymbol GetTypeSymbol(this Type type, Compilation compilation) { string basicType = type.GetFullTypeStr(); INamedTypeSymbol namedTypeSymbol = compilation.GetTypeByMetadataName(basicType); IEnumerable <Type> genericArgs = type.GetGenericArguments(); if (genericArgs.IsNullOrEmpty()) { return(namedTypeSymbol); } INamedTypeSymbol[] genericArgsTypeSymbols = genericArgs.Select(genArg => genArg.GetTypeSymbol(compilation)).ToArray(); namedTypeSymbol = namedTypeSymbol.Construct(genericArgsTypeSymbols); return(namedTypeSymbol); }
private static INamedTypeSymbol ConstructActionOrFunc( ITypeSymbol returnType, ImmutableArray <IParameterSymbol> parameters, SemanticModel semanticModel) { int length = parameters.Length; if (returnType.IsVoid()) { if (length == 0) { return(semanticModel.GetTypeByMetadataName("System.Action")); } INamedTypeSymbol actionSymbol = semanticModel.GetTypeByMetadataName($"System.Action`{length.ToString()}"); var typeArguments = new ITypeSymbol[length]; for (int i = 0; i < length; i++) { typeArguments[i] = parameters[i].Type; } return(actionSymbol.Construct(typeArguments)); } else { INamedTypeSymbol funcSymbol = semanticModel.GetTypeByMetadataName($"System.Func`{(length + 1).ToString()}"); var typeArguments = new ITypeSymbol[length + 1]; for (int i = 0; i < length; i++) { typeArguments[i] = parameters[i].Type; } typeArguments[length] = returnType; return(funcSymbol.Construct(typeArguments)); } }
public static ITypeSymbol?GetSymbolForType(this Compilation compilation, Type type) { if (type.FullName == null) { return(null); } if (!type.IsGenericType) { return(compilation.GetTypeByMetadataName(type.FullName)); } Type genericType = type.GetGenericTypeDefinition(); Type[] genericArgs = type.GetGenericArguments(); INamedTypeSymbol genericTypeSymbol = compilation.GetTypeByMetadataName(genericType.FullName !) !; ITypeSymbol[] genericArgSymbols = genericArgs.Select(t => compilation.GetSymbolForType(t) !).ToArray(); return(genericTypeSymbol.Construct(genericArgSymbols)); }
public static void ComputeCodeFix( CodeFixContext context, Diagnostic diagnostic, ExpressionSyntax expression, SemanticModel semanticModel) { TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken); ITypeSymbol expressionTypeSymbol = typeInfo.Type; if (expressionTypeSymbol == null) { return; } if (!expressionTypeSymbol.SupportsExplicitDeclaration()) { return; } (ISymbol symbol, ITypeSymbol typeSymbol) = GetContainingSymbolAndType(expression, semanticModel, context.CancellationToken); Debug.Assert(symbol != null, expression.ToString()); if (symbol == null) { return; } if (symbol.IsOverride) { return; } if (symbol.ImplementsInterfaceMember()) { return; } SyntaxNode node = symbol.GetSyntax(context.CancellationToken); if (node.Kind() == SyntaxKind.VariableDeclarator) { node = node.Parent.Parent; } TypeSyntax type = CSharpUtility.GetTypeOrReturnType(node); if (type == null) { return; } ITypeSymbol newTypeSymbol = expressionTypeSymbol; string additionalKey = null; bool isAsyncMethod = false; bool insertAwait = false; bool isYield = false; if (symbol.IsAsyncMethod()) { isAsyncMethod = true; INamedTypeSymbol taskOfT = semanticModel.GetTypeByMetadataName("System.Threading.Tasks.Task`1"); if (taskOfT == null) { return; } if (expression.Kind() == SyntaxKind.AwaitExpression) { newTypeSymbol = taskOfT.Construct(expressionTypeSymbol); } else if (expressionTypeSymbol.OriginalDefinition.Equals(taskOfT)) { insertAwait = true; additionalKey = "InsertAwait"; } else if (expressionTypeSymbol.HasMetadataName(MetadataNames.System_Threading_Tasks_Task)) { return; } } else if (expression.IsParentKind(SyntaxKind.YieldReturnStatement)) { isYield = true; newTypeSymbol = semanticModel .Compilation .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T) .Construct(expressionTypeSymbol); } if (!isYield && !isAsyncMethod && !typeSymbol.OriginalDefinition.IsIEnumerableOfT() && newTypeSymbol.OriginalDefinition.HasMetadataName(MetadataNames.System_Linq_IOrderedEnumerable_T)) { INamedTypeSymbol constructedEnumerableSymbol = semanticModel .Compilation .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T) .Construct(((INamedTypeSymbol)newTypeSymbol).TypeArguments.ToArray()); RegisterCodeFix(context, diagnostic, node, type, expression, constructedEnumerableSymbol, semanticModel, insertAwait: false); additionalKey = "IOrderedEnumerable<T>"; } RegisterCodeFix(context, diagnostic, node, type, expression, newTypeSymbol, semanticModel, insertAwait: insertAwait, additionalKey: additionalKey); }
public static INamedTypeSymbol TryConstruct(this INamedTypeSymbol type, ITypeSymbol[] typeArguments) => typeArguments.Length > 0 ? type.Construct(typeArguments) : type;
public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments) => namedType.Construct(typeArguments);
public static async Task ComputeRefactoringsAsync(RefactoringContext context, ExpressionSyntax expression) { if (expression != null) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol memberSymbol = GetContainingMethodOrPropertySymbol(expression, semanticModel, context.CancellationToken); if (memberSymbol != null) { SyntaxNode node = await memberSymbol .DeclaringSyntaxReferences[0] .GetSyntaxAsync(context.CancellationToken) .ConfigureAwait(false); var declaration = node as MemberDeclarationSyntax; if (declaration != null) { TypeSyntax memberType = GetMemberType(declaration); if (memberType != null) { ITypeSymbol memberTypeSymbol = semanticModel.GetTypeSymbol(memberType, context.CancellationToken); if (memberTypeSymbol != null) { ITypeSymbol expressionSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken); if (expressionSymbol?.IsErrorType() == false) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { ITypeSymbol newType = GetMemberNewType(memberSymbol, memberTypeSymbol, expression, expressionSymbol, semanticModel, context.CancellationToken); if (newType?.IsErrorType() == false && !memberTypeSymbol.Equals(newType) && !memberSymbol.IsOverride && !memberSymbol.ImplementsInterfaceMember()) { if (newType.IsNamedType() && memberTypeSymbol.IsNamedType()) { var newNamedType = (INamedTypeSymbol)newType; INamedTypeSymbol orderedEnumerableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Linq_IOrderedEnumerable_T); if (newNamedType.ConstructedFrom == orderedEnumerableSymbol) { INamedTypeSymbol enumerableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_Collections_Generic_IEnumerable_T); if (enumerableSymbol != null && ((INamedTypeSymbol)memberTypeSymbol).ConstructedFrom != enumerableSymbol) { RegisterChangeType(context, declaration, memberType, enumerableSymbol.Construct(newNamedType.TypeArguments.ToArray()), semanticModel); } } } RegisterChangeType(context, declaration, memberType, newType, semanticModel); } } if (context.IsAnyRefactoringEnabled(RefactoringIdentifiers.AddCastExpression, RefactoringIdentifiers.CallToMethod) && !memberTypeSymbol.IsErrorType()) { ITypeSymbol castTypeSymbol = GetCastTypeSymbol(memberSymbol, memberTypeSymbol, expressionSymbol, semanticModel); if (castTypeSymbol != null) { ModifyExpressionRefactoring.ComputeRefactoring( context, expression, castTypeSymbol, semanticModel); } } } } } } } } }
private static void AddMissingMembersToStatefulMarshaller(DocumentEditor editor, SyntaxNode declaringSyntax, INamedTypeSymbol marshallerType, ITypeSymbol managedType, HashSet <string> missingMemberNames, bool isLinearCollectionMarshaller) { SyntaxGenerator gen = editor.Generator; // Get the methods of the shape so we can use them to determine what types to use in signatures that are not obvious. var(_, methods) = StatefulMarshallerShapeHelper.GetShapeForType(marshallerType, managedType, isLinearCollectionMarshaller, editor.SemanticModel.Compilation); INamedTypeSymbol spanOfT = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_Span_Metadata) !; INamedTypeSymbol readOnlySpanOfT = editor.SemanticModel.Compilation.GetBestTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata) !; var(typeParameters, _) = marshallerType.GetAllTypeArgumentsIncludingInContainingTypes(); // Use a lazy factory for the type syntaxes to avoid re-checking the various methods and reconstructing the syntax. Lazy <SyntaxNode> unmanagedTypeSyntax = new(CreateUnmanagedTypeSyntax, isThreadSafe : false); Lazy <ITypeSymbol> managedElementTypeSymbol = new(CreateManagedElementTypeSymbol, isThreadSafe : false); List <SyntaxNode> newMembers = new(); if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromManaged)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.Value.Stateful.FromManaged, parameters: new[] { gen.ParameterDeclaration("managed", gen.TypeExpression(managedType)) }, accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToUnmanaged)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.Value.Stateful.ToUnmanaged, returnType: unmanagedTypeSyntax.Value, accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.FromUnmanaged)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.Value.Stateful.FromUnmanaged, parameters: new[] { gen.ParameterDeclaration("unmanaged", unmanagedTypeSyntax.Value) }, accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.Value.Stateful.ToManaged)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.Value.Stateful.ToManaged, returnType: gen.TypeExpression(managedType), accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.BufferSize)) { newMembers.Add( gen.WithAccessorDeclarations( gen.PropertyDeclaration(ShapeMemberNames.BufferSize, gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_Int32)), Accessibility.Public, DeclarationModifiers.Static), gen.GetAccessorDeclaration(statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) }))); } if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource, returnType: gen.TypeExpression(readOnlySpanOfT.Construct(managedElementTypeSymbol.Value)), accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination, returnType: gen.TypeExpression(spanOfT.Construct(typeParameters[typeParameters.Length - 1])), accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource, parameters: new[] { gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32)) }, returnType: gen.TypeExpression(readOnlySpanOfT.Construct(typeParameters[typeParameters.Length - 1])), accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination, parameters: new[] { gen.ParameterDeclaration("numElements", gen.TypeExpression(SpecialType.System_Int32)) }, returnType: gen.TypeExpression(spanOfT.Construct(managedElementTypeSymbol.Value)), accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } if (missingMemberNames.Contains(ShapeMemberNames.Free)) { newMembers.Add( gen.MethodDeclaration( ShapeMemberNames.Value.Stateful.Free, accessibility: Accessibility.Public, statements: new[] { DefaultMethodStatement(gen, editor.SemanticModel.Compilation) })); } editor.ReplaceNode(declaringSyntax, (declaringSyntax, gen) => gen.AddMembers(declaringSyntax, newMembers)); SyntaxNode CreateUnmanagedTypeSyntax() { ITypeSymbol?unmanagedType = null; if (methods.ToUnmanaged is not null) { unmanagedType = methods.ToUnmanaged.ReturnType; } else if (methods.FromUnmanaged is not null) { unmanagedType = methods.FromUnmanaged.Parameters[0].Type; } else if (methods.UnmanagedValuesSource is not null) { unmanagedType = methods.UnmanagedValuesSource.Parameters[0].Type; } else if (methods.UnmanagedValuesDestination is not null) { unmanagedType = methods.UnmanagedValuesDestination.Parameters[0].Type; } if (unmanagedType is not null) { return(gen.TypeExpression(unmanagedType)); } return(gen.TypeExpression(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr))); } ITypeSymbol CreateManagedElementTypeSymbol() { if (methods.ManagedValuesSource is not null) { return(((INamedTypeSymbol)methods.ManagedValuesSource.ReturnType).TypeArguments[0]); } if (methods.ManagedValuesDestination is not null) { return(((INamedTypeSymbol)methods.ManagedValuesDestination.ReturnType).TypeArguments[0]); } return(editor.SemanticModel.Compilation.GetSpecialType(SpecialType.System_IntPtr)); } }
public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments) { return(namedType.Construct(typeArguments)); }
protected override SyntaxNode AddAsyncKeywordAndTaskReturnType(SyntaxNode node, ITypeSymbol existingReturnType, INamedTypeSymbol taskTypeSymbol) { var methodNode = node as MethodDeclarationSyntax; if (methodNode == null) { return null; } if (taskTypeSymbol == null) { return null; } var returnType = taskTypeSymbol.Construct(existingReturnType).GenerateTypeSyntax(); return AddAsyncKeyword(methodNode.WithReturnType(returnType)); }
public ITypeSymbol Construct(INamedTypeSymbol namedType, ITypeSymbol[] typeArguments) { return namedType.Construct(typeArguments); }