Beispiel #1
0
        public AbstractData GetNodeData(SyntaxNode node,
                                        bool create = false,
                                        NamespaceData namespaceData = null,
                                        TypeData typeData           = null,
                                        MethodData methodData       = null)
        {
            AnonymousFunctionData functionData = null;
            SyntaxNode            endNode;

            if (methodData != null)
            {
                endNode = methodData.Node;
            }
            else if (typeData != null)
            {
                endNode = typeData.Node;
            }
            else if (namespaceData != null)
            {
                endNode = namespaceData.Node;
            }
            else
            {
                endNode = Node;
            }

            foreach (var n in node.AncestorsAndSelf()
                     .TakeWhile(o => !ReferenceEquals(o, endNode))
                     .Where(
                         o => _validDataKinds.Contains(o.Kind()))
                     .Reverse())
            {
                switch (n.Kind())
                {
                case SyntaxKind.ParenthesizedLambdaExpression:
                case SyntaxKind.AnonymousMethodExpression:
                case SyntaxKind.SimpleLambdaExpression:
                    if (methodData == null)
                    {
                        throw new InvalidOperationException($"Anonymous function {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var symbol = SemanticModel.GetSymbolInfo(n).Symbol as IMethodSymbol;
                    functionData = functionData != null
                                                        ? functionData.GetNestedAnonymousFunctionData((AnonymousFunctionExpressionSyntax)n, symbol, create)
                                                        : methodData.GetAnonymousFunctionData((AnonymousFunctionExpressionSyntax)n, symbol, create);

                    if (functionData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.MethodDeclaration:
                    if (typeData == null)
                    {
                        throw new InvalidOperationException($"Method {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var methodNode   = (MethodDeclarationSyntax)n;
                    var methodSymbol = SemanticModel.GetDeclaredSymbol(methodNode);
                    methodData = typeData.GetMethodData(methodNode, methodSymbol, create);
                    if (methodData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.ClassDeclaration:
                case SyntaxKind.InterfaceDeclaration:
                case SyntaxKind.StructDeclaration:
                    if (namespaceData == null)
                    {
                        namespaceData = GlobalNamespaceData;
                    }
                    var typeNode   = (TypeDeclarationSyntax)n;
                    var typeSymbol = SemanticModel.GetDeclaredSymbol(typeNode);
                    typeData = typeData != null
                                                        ? typeData.GetNestedTypeData(typeNode, typeSymbol, create)
                                                        : namespaceData.GetTypeData(typeNode, typeSymbol, create);

                    if (typeData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.NamespaceDeclaration:
                    var namespaceNode   = (NamespaceDeclarationSyntax)n;
                    var namespaceSymbol = SemanticModel.GetDeclaredSymbol(namespaceNode);
                    namespaceData = namespaceData != null
                                                        ? namespaceData.GetNestedNamespaceData(namespaceNode, namespaceSymbol, create)
                                                        : GetNamespaceData(namespaceNode, namespaceSymbol, create);

                    if (namespaceData == null)
                    {
                        return(null);
                    }
                    break;
                }
            }

            switch (node.Kind())
            {
            case SyntaxKind.ParenthesizedLambdaExpression:
            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
                return(functionData);

            case SyntaxKind.MethodDeclaration:
                return(methodData);

            case SyntaxKind.ClassDeclaration:
            case SyntaxKind.InterfaceDeclaration:
            case SyntaxKind.StructDeclaration:
                return(typeData);

            case SyntaxKind.NamespaceDeclaration:
                return(namespaceData);

            default:
                throw new InvalidOperationException($"Invalid node kind {Enum.GetName(typeof(SyntaxKind), node.Kind())}");
            }
        }
Beispiel #2
0
        public AbstractData GetNodeData(SyntaxNode node,
                                        bool create = false,
                                        NamespaceData namespaceData   = null,
                                        TypeData typeData             = null,
                                        BaseMethodData baseMethodData = null)
        {
            FunctionData  functionData = null;
            PropertyData  propertyData = null;
            BaseFieldData fieldData    = null;
            FieldVariableDeclaratorData fieldVariableData = null;
            SyntaxNode endNode;

            if (baseMethodData != null)
            {
                endNode = baseMethodData.GetNode();
            }
            else if (typeData != null)
            {
                endNode = typeData.Node;
            }
            else if (namespaceData != null)
            {
                endNode = namespaceData.Node;
            }
            else
            {
                endNode = Node;
            }

            foreach (var n in node.AncestorsAndSelf()
                     .TakeWhile(o => !ReferenceEquals(o, endNode))
                     .Where(IsValid)
                     .Reverse())
            {
                switch (n.Kind())
                {
                case SyntaxKind.ParenthesizedLambdaExpression:
                case SyntaxKind.AnonymousMethodExpression:
                case SyntaxKind.SimpleLambdaExpression:
                case SyntaxKind.LocalFunctionStatement:
                    if (baseMethodData == null)
                    {
                        // ParenthesizedLambda, AnonymousMethod and SimpleLambda can be also defined inside a type
                        if (!n.IsKind(SyntaxKind.LocalFunctionStatement))
                        {
                            if (typeData != null)
                            {
                                return(null);                                        // TODO: A type can have one or many FuncionData so we need to register them
                            }
                        }
                        throw new InvalidOperationException($"Anonymous function {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    functionData = functionData != null
                                                        ? functionData.GetChildFunction(n, SemanticModel, create)
                                                        : baseMethodData.GetChildFunction(n, SemanticModel, create);

                    if (functionData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.MethodDeclaration:
                    if (typeData == null)
                    {
                        throw new InvalidOperationException($"Method {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var methodNode = (MethodDeclarationSyntax)n;
                    baseMethodData = typeData.GetMethodData(methodNode, SemanticModel, create);
                    if (baseMethodData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.DestructorDeclaration:
                case SyntaxKind.ConstructorDeclaration:
                case SyntaxKind.OperatorDeclaration:
                case SyntaxKind.ConversionOperatorDeclaration:
                    if (typeData == null)
                    {
                        throw new InvalidOperationException($"Method {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var baseMethodNode = (BaseMethodDeclarationSyntax)n;
                    baseMethodData = typeData.GetSpecialMethodData(baseMethodNode, SemanticModel, create);
                    if (baseMethodData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.ArrowExpressionClause:
                    if (propertyData == null)
                    {
                        continue;
                    }
                    functionData = propertyData.GetAccessorData;
                    break;

                case SyntaxKind.GetAccessorDeclaration:
                    if (propertyData == null)
                    {
                        throw new InvalidOperationException($"Get accessor property {n} is declared outside a {nameof(PropertyDeclarationSyntax)}");
                    }
                    functionData = propertyData.GetAccessorData;
                    if (functionData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.SetAccessorDeclaration:
                    if (propertyData == null)
                    {
                        throw new InvalidOperationException($"Set accessor property {n} is declared outside a {nameof(PropertyDeclarationSyntax)}");
                    }
                    functionData = propertyData.SetAccessorData;
                    if (functionData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.PropertyDeclaration:
                    if (typeData == null)
                    {
                        throw new InvalidOperationException($"Property {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var propertyNode = (PropertyDeclarationSyntax)n;
                    propertyData = typeData.GetPropertyData(propertyNode, SemanticModel, create);
                    if (propertyData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.FieldDeclaration:
                case SyntaxKind.EventFieldDeclaration:
                    if (typeData == null)
                    {
                        throw new InvalidOperationException($"Field {n} is declared outside a {nameof(TypeDeclarationSyntax)}");
                    }
                    var fieldNode = (BaseFieldDeclarationSyntax)n;
                    fieldData = typeData.GetBaseFieldData(fieldNode, SemanticModel, create);
                    if (fieldData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.VariableDeclarator:
                    if (fieldData == null)
                    {
                        throw new InvalidOperationException($"Field {n} is declared outside a {nameof(BaseFieldDeclarationSyntax)}");
                    }
                    var variableNode = (VariableDeclaratorSyntax)n;
                    fieldVariableData = fieldData.GetVariableDeclaratorData(variableNode, SemanticModel);
                    if (fieldVariableData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.ClassDeclaration:
                case SyntaxKind.InterfaceDeclaration:
                case SyntaxKind.StructDeclaration:
                    if (namespaceData == null)
                    {
                        namespaceData = GlobalNamespace;
                    }
                    var typeNode = (TypeDeclarationSyntax)n;
                    typeData = typeData != null
                                                        ? typeData.GetNestedTypeData(typeNode, SemanticModel, create)
                                                        : namespaceData.GetTypeData(typeNode, SemanticModel, create);

                    if (typeData == null)
                    {
                        return(null);
                    }
                    break;

                case SyntaxKind.NamespaceDeclaration:
                    var namespaceNode = (NamespaceDeclarationSyntax)n;
                    namespaceData = namespaceData != null
                                                        ? namespaceData.GetNestedNamespaceData(namespaceNode, SemanticModel, create)
                                                        : GetNamespaceData(namespaceNode, create);

                    if (namespaceData == null)
                    {
                        return(null);
                    }
                    break;
                }
            }

            switch (node.Kind())
            {
            case SyntaxKind.ParenthesizedLambdaExpression:
            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.LocalFunctionStatement:
            case SyntaxKind.GetAccessorDeclaration:                     // Property getter
            case SyntaxKind.SetAccessorDeclaration:                     // Property setter
                return(functionData);

            case SyntaxKind.MethodDeclaration:
            case SyntaxKind.DestructorDeclaration:
            case SyntaxKind.ConstructorDeclaration:
            case SyntaxKind.OperatorDeclaration:
            case SyntaxKind.ConversionOperatorDeclaration:
                return(baseMethodData);

            case SyntaxKind.ClassDeclaration:
            case SyntaxKind.InterfaceDeclaration:
            case SyntaxKind.StructDeclaration:
                return(typeData);

            case SyntaxKind.NamespaceDeclaration:
                return(namespaceData);

            case SyntaxKind.PropertyDeclaration:
                return(propertyData);

            case SyntaxKind.FieldDeclaration:
            case SyntaxKind.EventFieldDeclaration:
                return(fieldData);

            case SyntaxKind.VariableDeclarator:
                return(fieldVariableData);

            case SyntaxKind.ArrowExpressionClause:                     // Arrow expression of a property getter or method
                return(functionData ?? baseMethodData);

            default:
                throw new InvalidOperationException($"Invalid node kind {Enum.GetName(typeof(SyntaxKind), node.Kind())}");
            }
        }