private static ITypeSymbol GetGenericType(SyntaxNode node, GenRef genRef, SemanticModel semanticModel) { if (node is InvocationExpressionSyntax) { ISymbol invokedSymbol = semanticModel.GetSymbolInfo(node).Symbol; // if is generic method if (genRef.Methods.Contains(invokedSymbol.OriginalDefinition)) { return ((IMethodSymbol)invokedSymbol).ReturnType; } } else if ((node is MemberAccessExpressionSyntax) && !(node.Parent is AssignmentExpressionSyntax)) { ISymbol invokedSymbol = semanticModel.GetSymbolInfo(node).Symbol; // if is generic property if (genRef.Properties.Contains(invokedSymbol.OriginalDefinition)) { return ((IPropertySymbol)invokedSymbol).Type; } } return null; }
private static GenRef FindGenericClassMembers(IEnumerable<SemanticModel> semanticModels) { // FIND // 1. Generic properties symbols // 2. Generic method symbols // ============================= var genericPropertiesList = new List<IPropertySymbol>(); var genericMethodsList = new List<IMethodSymbol>(); foreach (var semanticModel in semanticModels) { var tree = semanticModel.SyntaxTree; // Find generic classes var genericClassFinder = new GenericClassFinder(tree, semanticModel); var classDeclarations = genericClassFinder.Get().ToArray(); SyntaxNode newTree = tree.GetRoot(); // methods symbols var methodsToCast = classDeclarations .SelectMany(x => x.Members) .OfType<BaseMethodDeclarationSyntax>() .Select(x => (IMethodSymbol)semanticModel.GetDeclaredSymbol(x)); genericMethodsList.AddRange(methodsToCast); // properties symbols var propertiesToCast = classDeclarations .SelectMany(x => x.Members) .OfType<BasePropertyDeclarationSyntax>() .Select(x => (IPropertySymbol)semanticModel.GetDeclaredSymbol(x)); genericPropertiesList.AddRange(propertiesToCast); } var genRefs = new GenRef(genericMethodsList, genericPropertiesList); return genRefs; }
private static SyntaxNode CastResursiveMethod(SyntaxNode tree, SemanticModel semanticModel, GenRef genRef, Dictionary<SyntaxNode, SyntaxNode> castChanges) { var change = new Dictionary<SyntaxNode, SyntaxNode>(); foreach (var node in tree.ChildNodes()) { // recurse for changed node var casted = CastResursiveMethod(node, semanticModel, genRef, castChanges); var ts = GetGenericType(node, genRef, semanticModel); if (ts != null) { casted = Helpers.CastTo((ExpressionSyntax)casted, ts); if (node.Parent is MemberAccessExpressionSyntax) casted = ((ExpressionSyntax)casted).Parenthesize(); castChanges.Add(node, casted); } if (node != casted) change.Add(node, casted); } if (change.Any()) tree = tree.ReplaceNodes(change.Keys, (x, y) => change[x]); return tree; }