Ejemplo n.º 1
0
        public JsExpression VisitUnaryExpression(ExpressionSyntax node, ExpressionSyntax expression)
        {
            ExpressionType op;

            switch (node.CSharpKind())
            {
            case SyntaxKind.LogicalNotExpression:
                op = ExpressionType.Not;
                break;

            case SyntaxKind.UnaryMinusExpression:
                op = ExpressionType.Negate;
                break;

            case SyntaxKind.PostDecrementExpression:
            case SyntaxKind.PostIncrementExpression:
                throw new Exception("Expression trees cannot contain assignment operators.");

            default:
                throw new Exception("Unknown operation: " + node.CSharpKind());
            }

            var makeUnary    = GetExpressionMethod("MakeUnary", Context.Instance.ExpressionType, Context.Instance.Expression, Context.Instance.TypeType);
            var opExpression = idioms.GetEnumValue(Context.Instance.ExpressionType.GetMembers(op.ToString()).OfType <IFieldSymbol>().Single());
            var operand      = expression.Accept(this);
            var type         = model.GetTypeInfo(node).ConvertedType;

            return(idioms.InvokeStatic(
                       makeUnary,
                       opExpression,
                       operand,
                       idioms.TypeOf(type)));
        }
Ejemplo n.º 2
0
        public static TypeSyntax ConstantType(ExpressionSyntax value)
        {
            var valueStr = value.ToString();

            switch (value.CSharpKind())
            {
            case SyntaxKind.NumericLiteralExpression:
            {
                int    val;
                double dval;
                if (int.TryParse(valueStr, out val))
                {
                    return(Compiler.Int);
                }
                else if (double.TryParse(valueStr, out dval))
                {
                    return(Compiler.Double);
                }

                break;
            }

            case SyntaxKind.StringLiteralExpression:
                return(Compiler.String);

            case SyntaxKind.TrueLiteralExpression:
            case SyntaxKind.FalseLiteralExpression:
                return(Compiler.Boolean);
            }

            return(SyntaxFactory.ParseTypeName(valueStr));
        }
Ejemplo n.º 3
0
        public void ParseExpression()
        {
            ExpressionSyntax expression = SyntaxFactory.ParseExpression("1 + 2");

            if (expression.CSharpKind() == SyntaxKind.AddExpression)
            {
                BinaryExpressionSyntax binaryExpression = (BinaryExpressionSyntax)expression;
                SyntaxToken            operatorToken    = binaryExpression.OperatorToken;
                Assert.AreEqual("+", operatorToken.ToString());

                ExpressionSyntax left = binaryExpression.Left;
                Assert.AreEqual(SyntaxKind.NumericLiteralExpression, left.CSharpKind());
            }
        }
Ejemplo n.º 4
0
        private static bool IsAssignmentOfPropertyValueParameterToBackingField(
            ExpressionSyntax expression,
            IFieldSymbol backingField,
            SemanticModel semanticModel)
        {
            if (expression.CSharpKind() != SyntaxKind.SimpleAssignmentExpression)
            {
                return(false);
            }

            var assignment = (AssignmentExpressionSyntax)expression;

            return(IsBackingField(assignment.Left, backingField, semanticModel) &&
                   IsPropertyValueParameter(assignment.Right, semanticModel));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Decomposes a name or member access expression into its component parts.
        /// </summary>
        /// <param name="expression">The name or member access expression.</param>
        /// <param name="qualifier">The qualifier (or left-hand-side) of the name expression. This may be null if there is no qualifier.</param>
        /// <param name="name">The name of the expression.</param>
        /// <param name="arity">The number of generic type parameters.</param>
        private static void DecomposeName(ExpressionSyntax expression, out ExpressionSyntax qualifier, out string name, out int arity)
        {
            switch (expression.CSharpKind())
            {
            case SyntaxKind.SimpleMemberAccessExpression:
            case SyntaxKind.PointerMemberAccessExpression:
                var max = (MemberAccessExpressionSyntax)expression;
                qualifier = max.Expression;
                name      = max.Name.Identifier.ValueText;
                arity     = max.Name.Arity;
                break;

            case SyntaxKind.QualifiedName:
                var qn = (QualifiedNameSyntax)expression;
                qualifier = qn.Left;
                name      = qn.Right.Identifier.ValueText;
                arity     = qn.Arity;
                break;

            case SyntaxKind.AliasQualifiedName:
                var aq = (AliasQualifiedNameSyntax)expression;
                qualifier = aq.Alias;
                name      = aq.Name.Identifier.ValueText;
                arity     = aq.Name.Arity;
                break;

            case SyntaxKind.GenericName:
                var gx = (GenericNameSyntax)expression;
                qualifier = null;
                name      = gx.Identifier.ValueText;
                arity     = gx.Arity;
                break;

            case SyntaxKind.IdentifierName:
                var nx = (IdentifierNameSyntax)expression;
                qualifier = null;
                name      = nx.Identifier.ValueText;
                arity     = 0;
                break;

            default:
                qualifier = null;
                name      = null;
                arity     = 0;
                break;
            }
        }
 /// <summary>
 /// Decomposes a name or member access expression into its component parts.
 /// </summary>
 /// <param name="expression">The name or member access expression.</param>
 /// <param name="qualifier">The qualifier (or left-hand-side) of the name expression. This may be null if there is no qualifier.</param>
 /// <param name="name">The name of the expression.</param>
 /// <param name="arity">The number of generic type parameters.</param>
 private static void DecomposeName(ExpressionSyntax expression, out ExpressionSyntax qualifier, out string name, out int arity)
 {
     switch (expression.CSharpKind())
     {
         case SyntaxKind.SimpleMemberAccessExpression:
         case SyntaxKind.PointerMemberAccessExpression:
             var max = (MemberAccessExpressionSyntax)expression;
             qualifier = max.Expression;
             name = max.Name.Identifier.ValueText;
             arity = max.Name.Arity;
             break;
         case SyntaxKind.QualifiedName:
             var qn = (QualifiedNameSyntax)expression;
             qualifier = qn.Left;
             name = qn.Right.Identifier.ValueText;
             arity = qn.Arity;
             break;
         case SyntaxKind.AliasQualifiedName:
             var aq = (AliasQualifiedNameSyntax)expression;
             qualifier = aq.Alias;
             name = aq.Name.Identifier.ValueText;
             arity = aq.Name.Arity;
             break;
         case SyntaxKind.GenericName:
             var gx = (GenericNameSyntax)expression;
             qualifier = null;
             name = gx.Identifier.ValueText;
             arity = gx.Arity;
             break;
         case SyntaxKind.IdentifierName:
             var nx = (IdentifierNameSyntax)expression;
             qualifier = null;
             name = nx.Identifier.ValueText;
             arity = 0;
             break;
         default:
             qualifier = null;
             name = null;
             arity = 0;
             break;
     }
 }
            private ExpressionSyntax TryAddTypeArgumentToIdentifierName(ExpressionSyntax newNode, ISymbol symbol)
            {
                if (newNode.CSharpKind() == SyntaxKind.IdentifierName && symbol.Kind == SymbolKind.Method)
                {
                    if (((IMethodSymbol)symbol).TypeArguments.Length != 0)
                    {
                        var typeArguments = ((IMethodSymbol)symbol).TypeArguments;

                        var genericName = SyntaxFactory.GenericName(
                            ((IdentifierNameSyntax)newNode).Identifier,
                            SyntaxFactory.TypeArgumentList(
                                SyntaxFactory.SeparatedList(
                                    typeArguments.Select(p => SyntaxFactory.ParseTypeName(p.ToDisplayParts(TypeNameFormatWithGenerics).ToDisplayString())))))
                                          .WithLeadingTrivia(newNode.GetLeadingTrivia())
                                          .WithTrailingTrivia(newNode.GetTrailingTrivia())
                                          .WithAdditionalAnnotations(Simplifier.Annotation);

                        genericName = newNode.CopyAnnotationsTo(genericName);
                        return(genericName);
                    }
                }

                return(newNode);
            }
Ejemplo n.º 8
0
        private static bool WillConflictWithExistingLocal(ExpressionSyntax expression, ExpressionSyntax simplifiedNode)
        {
            if (simplifiedNode.CSharpKind() == SyntaxKind.IdentifierName && !SyntaxFacts.IsInNamespaceOrTypeContext(expression))
            {
                var identifierName = (IdentifierNameSyntax)simplifiedNode;
                var enclosingDeclarationSpace = FindImmediatelyEnclosingLocalVariableDeclarationSpace(expression);
                var enclosingMemberDeclaration = expression.FirstAncestorOrSelf<MemberDeclarationSyntax>();
                if (enclosingDeclarationSpace != null && enclosingMemberDeclaration != null)
                {
                    var locals = enclosingMemberDeclaration.GetLocalDeclarationMap()[identifierName.Identifier.ValueText];
                    foreach (var token in locals)
                    {
                        if (token.GetAncestors<SyntaxNode>().Contains(enclosingDeclarationSpace))
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }
Ejemplo n.º 9
0
        private static bool IsNullableTypeInPointerExpression(ExpressionSyntax expression, ExpressionSyntax simplifiedNode)
        {
            // Note: nullable type syntax is not allowed in pointer type syntax
            if (simplifiedNode.CSharpKind() == SyntaxKind.NullableType &&
                simplifiedNode.DescendantNodes().Any(n => n is PointerTypeSyntax))
            {
                return true;
            }

            return false;
        }
Ejemplo n.º 10
0
        public static TypeSyntax ConstantType(ExpressionSyntax value)
        {
            var valueStr = value.ToString();
            switch (value.CSharpKind())
            {
                case SyntaxKind.NumericLiteralExpression:
                {
                    int val;
                    double dval;
                    if (int.TryParse(valueStr, out val))
                        return Compiler.Int;
                    else if (double.TryParse(valueStr, out dval))
                        return Compiler.Double;

                    break;
                }

                case SyntaxKind.StringLiteralExpression:
                    return Compiler.String;

                case SyntaxKind.TrueLiteralExpression:
                case SyntaxKind.FalseLiteralExpression:
                    return Compiler.Boolean;
            }

            return SyntaxFactory.ParseTypeName(valueStr);
        }
Ejemplo n.º 11
0
        private static bool IsAssignmentOfPropertyValueParameterToBackingField(
            ExpressionSyntax expression,
            IFieldSymbol backingField,
            SemanticModel semanticModel)
        {
            if (expression.CSharpKind() != SyntaxKind.SimpleAssignmentExpression)
            {
                return false;
            }

            var assignment = (BinaryExpressionSyntax)expression;

            return IsBackingField(assignment.Left, backingField, semanticModel)
                && IsPropertyValueParameter(assignment.Right, semanticModel);
        }
            private ExpressionSyntax FullyQualifyIdentifierName(
                ISymbol symbol,
                ExpressionSyntax rewrittenNode,
                ExpressionSyntax originalNode,
                bool replaceNode,
                bool isInsideCref,
                bool omitLeftHandSide)
            {
                Debug.Assert(!replaceNode || rewrittenNode.CSharpKind() == SyntaxKind.IdentifierName);

                //// TODO: use and expand Generate*Syntax(isymbol) to not depend on symbol display any more.
                //// See GenerateExpressionSyntax();

                var result = rewrittenNode;

                // only if this symbol has a containing type or namespace there is work for us to do.
                if (replaceNode || symbol.ContainingType != null || symbol.ContainingNamespace != null)
                {
                    ImmutableArray <SymbolDisplayPart> displayParts;

                    ExpressionSyntax left = null;

                    // we either need to create an AliasQualifiedName if the symbol is directly contained in the global namespace,
                    // otherwise it a QualifiedName.
                    if (!replaceNode && symbol.ContainingType == null && symbol.ContainingNamespace.IsGlobalNamespace)
                    {
                        return(rewrittenNode.CopyAnnotationsTo(
                                   SyntaxFactory.AliasQualifiedName(
                                       SyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.GlobalKeyword)),
                                       (SimpleNameSyntax)rewrittenNode.WithLeadingTrivia(null))
                                   .WithLeadingTrivia(rewrittenNode.GetLeadingTrivia())));
                    }

                    displayParts = replaceNode
                        ? symbol.ToDisplayParts(TypeNameFormatWithGenerics)
                        : ((ISymbol)symbol.ContainingType ?? (ISymbol)symbol.ContainingNamespace).ToDisplayParts(TypeNameFormatWithGenerics);

                    rewrittenNode = TryAddTypeArgumentToIdentifierName(rewrittenNode, symbol);

                    // Replaces the '<' token with the '{' token since we are inside crefs
                    rewrittenNode = TryReplaceAngleBracesWithCurlyBraces(rewrittenNode, isInsideCref);
                    result        = rewrittenNode;

                    if (!omitLeftHandSide)
                    {
                        left = SyntaxFactory.ParseTypeName(displayParts.ToDisplayString());

                        // Replaces the '<' token with the '{' token since we are inside crefs
                        left = TryReplaceAngleBracesWithCurlyBraces(left, isInsideCref);

                        if (replaceNode)
                        {
                            return(left
                                   .WithLeadingTrivia(rewrittenNode.GetLeadingTrivia())
                                   .WithTrailingTrivia(rewrittenNode.GetTrailingTrivia()));
                        }

                        // now create syntax for the combination of left and right syntax, or a simple replacement in case of an identifier
                        var parent        = originalNode.Parent;
                        var leadingTrivia = rewrittenNode.GetLeadingTrivia();
                        rewrittenNode = rewrittenNode.WithLeadingTrivia(null);

                        switch (parent.CSharpKind())
                        {
                        case SyntaxKind.QualifiedName:
                            var qualifiedParent = (QualifiedNameSyntax)parent;

                            result = rewrittenNode.CopyAnnotationsTo(
                                SyntaxFactory.QualifiedName(
                                    (NameSyntax)left,
                                    (SimpleNameSyntax)rewrittenNode));

                            break;

                        case SyntaxKind.SimpleMemberAccessExpression:
                            var memberAccessParent = (MemberAccessExpressionSyntax)parent;

                            result = rewrittenNode.CopyAnnotationsTo(
                                SyntaxFactory.MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    left,
                                    (SimpleNameSyntax)rewrittenNode));

                            break;

                        default:
                            Debug.Assert(rewrittenNode is SimpleNameSyntax);

                            if (SyntaxFacts.IsInNamespaceOrTypeContext(originalNode))
                            {
                                var right = (SimpleNameSyntax)rewrittenNode;
                                result = rewrittenNode.CopyAnnotationsTo(SyntaxFactory.QualifiedName((NameSyntax)left, right.WithAdditionalAnnotations(Simplifier.SpecialTypeAnnotation)));
                            }
                            else if (originalNode.Parent is CrefSyntax)
                            {
                                var right = (SimpleNameSyntax)rewrittenNode;
                                result = rewrittenNode.CopyAnnotationsTo(SyntaxFactory.QualifiedName((NameSyntax)left, right));
                            }
                            else
                            {
                                result = rewrittenNode.CopyAnnotationsTo(
                                    SyntaxFactory.MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        left,
                                        (SimpleNameSyntax)rewrittenNode));
                            }

                            break;
                        }

                        result = result.WithLeadingTrivia(leadingTrivia);
                    }
                }

                return(result);
            }
            private ExpressionSyntax VisitSimpleName(SimpleNameSyntax rewrittenSimpleName, SimpleNameSyntax originalSimpleName)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // if this is "var", then do not process further
                if (originalSimpleName.IsVar)
                {
                    return(rewrittenSimpleName);
                }

                var identifier           = rewrittenSimpleName.Identifier;
                ExpressionSyntax newNode = rewrittenSimpleName;

                var isInsideCref = originalSimpleName.AncestorsAndSelf(ascendOutOfTrivia: true).Any(n => n is CrefSyntax);

                ////
                //// 1. if this identifier is an alias, we'll expand it here and replace the node completely.
                ////
                if (!SyntaxFacts.IsAliasQualifier(originalSimpleName))
                {
                    var aliasInfo = semanticModel.GetAliasInfo(originalSimpleName, cancellationToken);
                    if (aliasInfo != null)
                    {
                        var aliasTarget = aliasInfo.Target;

                        if (aliasTarget.IsNamespace() && ((INamespaceSymbol)aliasTarget).IsGlobalNamespace)
                        {
                            return(rewrittenSimpleName);
                        }

                        // if the enclosing expression is a typeof expression that already contains open type we cannot
                        // we need to insert an open type as well.
                        var typeOfExpression = originalSimpleName.GetAncestor <TypeOfExpressionSyntax>();
                        if (typeOfExpression != null && IsTypeOfUnboundGenericType(semanticModel, typeOfExpression))
                        {
                            aliasTarget = ((INamedTypeSymbol)aliasTarget).ConstructUnboundGenericType();
                        }

                        // the expanded form replaces the current identifier name.
                        var replacement = FullyQualifyIdentifierName(
                            aliasTarget,
                            newNode,
                            originalSimpleName,
                            replaceNode: true,
                            isInsideCref: isInsideCref,
                            omitLeftHandSide: false)
                                          .WithAdditionalAnnotations(Simplifier.Annotation);

                        // We replace the simple name completely, so we can't continue and rename the token
                        // with a RenameLocationAnnotation.
                        // There's also no way of removing annotations, so we just add a DoNotRenameAnnotation.
                        if (replacement.CSharpKind() == SyntaxKind.AliasQualifiedName)
                        {
                            var qualifiedReplacement = (AliasQualifiedNameSyntax)replacement;

                            var newIdentifier = identifier.CopyAnnotationsTo(qualifiedReplacement.Name.Identifier);

                            if (this.annotationForReplacedAliasIdentifier != null)
                            {
                                newIdentifier = newIdentifier.WithAdditionalAnnotations(annotationForReplacedAliasIdentifier);
                            }

                            var aliasAnnotationInfo = AliasAnnotation.Create(aliasInfo.Name);

                            newIdentifier = newIdentifier.WithAdditionalAnnotations(aliasAnnotationInfo);

                            replacement = replacement.ReplaceNode(
                                qualifiedReplacement.Name,
                                qualifiedReplacement.Name.WithIdentifier(newIdentifier));

                            replacement = newNode.CopyAnnotationsTo(replacement);

                            var         firstReplacementToken = replacement.GetFirstToken(true, false, true, true);
                            var         firstOriginalToken    = originalSimpleName.GetFirstToken(true, false, true, true);
                            SyntaxToken tokenWithLeadingWhitespace;
                            if (TryAddLeadingElasticTriviaIfNecessary(firstReplacementToken, firstOriginalToken, out tokenWithLeadingWhitespace))
                            {
                                replacement = replacement.ReplaceToken(firstOriginalToken, tokenWithLeadingWhitespace);
                            }

                            replacement = AppendElasticTriviaIfNecessary(replacement, originalSimpleName);

                            return(replacement);
                        }

                        if (replacement.CSharpKind() == SyntaxKind.QualifiedName)
                        {
                            var qualifiedReplacement = (QualifiedNameSyntax)replacement;

                            var newIdentifier = identifier.CopyAnnotationsTo(qualifiedReplacement.Right.Identifier);

                            if (this.annotationForReplacedAliasIdentifier != null)
                            {
                                newIdentifier = newIdentifier.WithAdditionalAnnotations(annotationForReplacedAliasIdentifier);
                            }

                            var aliasAnnotationInfo = AliasAnnotation.Create(aliasInfo.Name);

                            newIdentifier = newIdentifier.WithAdditionalAnnotations(aliasAnnotationInfo);

                            replacement = replacement.ReplaceNode(
                                qualifiedReplacement.Right,
                                qualifiedReplacement.Right.WithIdentifier(newIdentifier));

                            replacement = newNode.CopyAnnotationsTo(replacement);

                            replacement = AppendElasticTriviaIfNecessary(replacement, originalSimpleName);

                            return(replacement);
                        }

                        throw new NotImplementedException();
                    }
                }

                var symbol = semanticModel.GetSymbolInfo(originalSimpleName.Identifier).Symbol;

                if (symbol == null)
                {
                    return(newNode);
                }

                var typeArgumentSymbols      = TypeArgumentSymbolsPresentInName(originalSimpleName);
                var omitLeftSideOfExpression = false;

                // Check to see if the type Arguments in the resultant Symbol is recursively defined.
                if (IsTypeArgumentDefinedRecursive(symbol, typeArgumentSymbols, enterContainingSymbol: true))
                {
                    if (symbol.ContainingSymbol.Equals(symbol.OriginalDefinition.ContainingSymbol) &&
                        symbol.Kind == SymbolKind.Method &&
                        ((IMethodSymbol)symbol).IsStatic)
                    {
                        if (IsTypeArgumentDefinedRecursive(symbol, typeArgumentSymbols, enterContainingSymbol: false))
                        {
                            return(newNode);
                        }
                        else
                        {
                            omitLeftSideOfExpression = true;
                        }
                    }
                    else
                    {
                        return(newNode);
                    }
                }

                if (IsInvocationWithDynamicArguments(originalSimpleName, semanticModel))
                {
                    return(newNode);
                }

                ////
                //// 2. If it's an attribute, make sure the identifier matches the attribute's class name.
                ////
                if (originalSimpleName.GetAncestor <AttributeSyntax>() != null)
                {
                    if (symbol.IsConstructor() && symbol.ContainingType.IsAttribute())
                    {
                        symbol = symbol.ContainingType;
                        var name = symbol.Name;

                        Debug.Assert(name.StartsWith(originalSimpleName.Identifier.ValueText));

                        // if the user already used the Attribute suffix in the attribute, we'll maintain it.
                        if (identifier.ValueText == name && name.EndsWith("Attribute"))
                        {
                            identifier = identifier.WithAdditionalAnnotations(SimplificationHelpers.DontSimplifyAnnotation);
                        }

                        identifier = identifier.CopyAnnotationsTo(SyntaxFactory.VerbatimIdentifier(identifier.LeadingTrivia, name, name, identifier.TrailingTrivia));
                    }
                }

                ////
                //// 3. Always try to escape keyword identifiers
                ////
                identifier = TryEscapeIdentifierToken(identifier, originalSimpleName, semanticModel).WithAdditionalAnnotations(Simplifier.Annotation);
                if (identifier != rewrittenSimpleName.Identifier)
                {
                    switch (newNode.CSharpKind())
                    {
                    case SyntaxKind.IdentifierName:
                    case SyntaxKind.GenericName:
                        newNode = ((SimpleNameSyntax)newNode).WithIdentifier(identifier);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                }

                var parent = originalSimpleName.Parent;

                // do not complexify further for location where only simple names are allowed
                if (parent is MemberDeclarationSyntax ||
                    originalSimpleName.GetAncestor <NameEqualsSyntax>() != null ||
                    (parent is MemberAccessExpressionSyntax && parent.CSharpKind() != SyntaxKind.SimpleMemberAccessExpression) ||
                    ((parent.CSharpKind() == SyntaxKind.SimpleMemberAccessExpression || parent.CSharpKind() == SyntaxKind.NameMemberCref) && originalSimpleName.IsRightSideOfDot()) ||
                    (parent.CSharpKind() == SyntaxKind.QualifiedName && originalSimpleName.IsRightSideOfQualifiedName()) ||
                    (parent.CSharpKind() == SyntaxKind.AliasQualifiedName))
                {
                    return(TryAddTypeArgumentToIdentifierName(newNode, symbol));
                }

                ////
                //// 4. If this is a standalone identifier or the left side of a qualified name or member access try to fully qualify it
                ////

                // we need to treat the constructor as type name, so just get the containing type.
                if (symbol.IsConstructor() && (parent.CSharpKind() == SyntaxKind.ObjectCreationExpression || parent.CSharpKind() == SyntaxKind.NameMemberCref))
                {
                    symbol = symbol.ContainingType;
                }

                // if it's a namespace or type name, fully qualify it.
                if (symbol.Kind == SymbolKind.NamedType ||
                    symbol.Kind == SymbolKind.Namespace)
                {
                    var replacement = FullyQualifyIdentifierName(
                        (INamespaceOrTypeSymbol)symbol,
                        newNode,
                        originalSimpleName,
                        replaceNode: false,
                        isInsideCref: isInsideCref,
                        omitLeftHandSide: omitLeftSideOfExpression)
                                      .WithAdditionalAnnotations(Simplifier.Annotation);

                    replacement = AppendElasticTriviaIfNecessary(replacement, originalSimpleName);

                    return(replacement);
                }

                // if it's a member access, we're fully qualifying the left side and make it a member access.
                if (symbol.Kind == SymbolKind.Method ||
                    symbol.Kind == SymbolKind.Field ||
                    symbol.Kind == SymbolKind.Property)
                {
                    if (symbol.IsStatic || originalSimpleName.IsParentKind(SyntaxKind.NameMemberCref))
                    {
                        newNode = FullyQualifyIdentifierName(
                            symbol,
                            newNode,
                            originalSimpleName,
                            replaceNode: false,
                            isInsideCref: isInsideCref,
                            omitLeftHandSide: omitLeftSideOfExpression);
                    }
                    else
                    {
                        if (!IsPropertyNameOfObjectInitializer(originalSimpleName))
                        {
                            ExpressionSyntax left;

                            // Assumption here is, if the enclosing and containing types are different then there is Inheritence relationship
                            if (semanticModel.GetEnclosingNamedType(originalSimpleName.SpanStart, cancellationToken) != symbol.ContainingType)
                            {
                                left = SyntaxFactory.BaseExpression();
                            }
                            else
                            {
                                left = SyntaxFactory.ThisExpression();
                            }

                            var identifiersLeadingTrivia = newNode.GetLeadingTrivia();
                            newNode = TryAddTypeArgumentToIdentifierName(newNode, symbol);

                            newNode = SyntaxFactory.MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                left,
                                (SimpleNameSyntax)newNode.WithLeadingTrivia(null))
                                      .WithLeadingTrivia(identifiersLeadingTrivia);
                        }
                    }
                }

                var result = newNode.WithAdditionalAnnotations(Simplifier.Annotation);

                result = AppendElasticTriviaIfNecessary(result, originalSimpleName);

                return(result);
            }
Ejemplo n.º 14
0
        public void FlattenCondition(ExpressionSyntax expr, string prefix, bool ss_jump_if_value, string ss_jump_label, List<FlatStatement> instructions)
        {
            if (expr is LiteralExpressionSyntax)
            {
                switch (expr.CSharpKind())
                {
                    case SyntaxKind.TrueLiteralExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JMP(FlatOperand.LabelRef(ss_jump_label)));
                        return;
                    case SyntaxKind.FalseLiteralExpression:
                        if (!ss_jump_if_value)
                            instructions.Add(FlatStatement.JMP(FlatOperand.LabelRef(ss_jump_label)));
                        return;
                }
                throw new NotImplementedException("literal expression " + expr.CSharpKind().ToString());
            }
            if (expr is BinaryExpressionSyntax)
            {
                BinaryExpressionSyntax condition = expr as BinaryExpressionSyntax;

                switch (condition.CSharpKind())
                {
                    case SyntaxKind.LogicalAndExpression:
                        {
                            FlattenCondition(condition.Left, prefix, ss_jump_if_value, ss_jump_label, instructions);
                            // fell through because left side didnt match. check right side
                            FlattenCondition(condition.Right, prefix, ss_jump_if_value, ss_jump_label, instructions);
                            // fell through because right side didnt match either.
                            return;
                        }
                        break;
                    case SyntaxKind.LogicalOrExpression:
                        {
                            string ifEnterLabel = prefix + MakeUniqueLabelPrefix("shortcircuit");
                            FlattenCondition(condition.Left, prefix, !ss_jump_if_value, ifEnterLabel, instructions); // short circuit if left side matches
                            // fell through because left side didn't match. check right side
                            FlattenCondition(condition.Right, prefix, ss_jump_if_value, ss_jump_label, instructions);

                            instructions.Add(FlatStatement.LABEL(FlatOperand.LabelRef(ifEnterLabel)));
                            return;
                        }
                        break;
                    case SyntaxKind.IsExpression:
                        {
                            FlatOperand fop_result = ResolveExpression(expr, null, instructions);
                            if (ss_jump_if_value)
                                instructions.Add(FlatStatement.JNZ(FlatOperand.LabelRef(ss_jump_label), fop_result));
                            else
                                instructions.Add(FlatStatement.JZ(FlatOperand.LabelRef(ss_jump_label), fop_result));
                        }
                        return;

                }

                FlatOperand opnd_left = ResolveExpression(condition.Left, null, instructions);
                FlatOperand opnd_right = ResolveExpression(condition.Right, null, instructions);

                switch (condition.CSharpKind())
                {
                    case SyntaxKind.GreaterThanOrEqualExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JGE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JL(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    case SyntaxKind.GreaterThanExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JG(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JLE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    case SyntaxKind.LessThanExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JL(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JGE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    case SyntaxKind.LessThanOrEqualExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JLE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JG(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    case SyntaxKind.NotEqualsExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JNE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    case SyntaxKind.EqualsExpression:
                        if (ss_jump_if_value)
                            instructions.Add(FlatStatement.JE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        else
                            instructions.Add(FlatStatement.JNE(FlatOperand.LabelRef(ss_jump_label), opnd_left, opnd_right));
                        return;
                    default:
                        throw new NotImplementedException("binary expression " + condition.CSharpKind());
                }

                throw new NotImplementedException();
            }

            TypeInfo ti = Model.GetTypeInfo(expr);
            if (ti.ConvertedType.SpecialType == SpecialType.System_Boolean)
            {
                FlatOperand fop_result = ResolveExpression(expr, null, instructions);
                if (ss_jump_if_value)
                    instructions.Add(FlatStatement.JNZ(FlatOperand.LabelRef(ss_jump_label), fop_result));
                else
                    instructions.Add(FlatStatement.JZ(FlatOperand.LabelRef(ss_jump_label), fop_result));
                return;

            }

            throw new NotImplementedException();
        }
            private ExpressionSyntax FullyQualifyIdentifierName(
                ISymbol symbol,
                ExpressionSyntax rewrittenNode,
                ExpressionSyntax originalNode,
                bool replaceNode,
                bool isInsideCref,
                bool omitLeftHandSide)
            {
                Debug.Assert(!replaceNode || rewrittenNode.CSharpKind() == SyntaxKind.IdentifierName);

                //// TODO: use and expand Generate*Syntax(isymbol) to not depend on symbol display any more.
                //// See GenerateExpressionSyntax();

                var result = rewrittenNode;

                // only if this symbol has a containing type or namespace there is work for us to do.
                if (replaceNode || symbol.ContainingType != null || symbol.ContainingNamespace != null)
                {
                    ImmutableArray<SymbolDisplayPart> displayParts;

                    ExpressionSyntax left = null;

                    // we either need to create an AliasQualifiedName if the symbol is directly contained in the global namespace,
                    // otherwise it a QualifiedName.
                    if (!replaceNode && symbol.ContainingType == null && symbol.ContainingNamespace.IsGlobalNamespace)
                    {
                        return rewrittenNode.CopyAnnotationsTo(
                            SyntaxFactory.AliasQualifiedName(
                                SyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.GlobalKeyword)),
                                (SimpleNameSyntax)rewrittenNode.WithLeadingTrivia(null))
                                    .WithLeadingTrivia(rewrittenNode.GetLeadingTrivia()));
                    }

                    displayParts = replaceNode
                        ? symbol.ToDisplayParts(TypeNameFormatWithGenerics)
                        : ((ISymbol)symbol.ContainingType ?? (ISymbol)symbol.ContainingNamespace).ToDisplayParts(TypeNameFormatWithGenerics);

                    rewrittenNode = TryAddTypeArgumentToIdentifierName(rewrittenNode, symbol);

                    // Replaces the '<' token with the '{' token since we are inside crefs
                    rewrittenNode = TryReplaceAngleBracesWithCurlyBraces(rewrittenNode, isInsideCref);
                    result = rewrittenNode;

                    if (!omitLeftHandSide)
                    {
                        left = SyntaxFactory.ParseTypeName(displayParts.ToDisplayString());

                        // Replaces the '<' token with the '{' token since we are inside crefs
                        left = TryReplaceAngleBracesWithCurlyBraces(left, isInsideCref);

                        if (replaceNode)
                        {
                            return left
                                .WithLeadingTrivia(rewrittenNode.GetLeadingTrivia())
                                    .WithTrailingTrivia(rewrittenNode.GetTrailingTrivia());
                        }

                        // now create syntax for the combination of left and right syntax, or a simple replacement in case of an identifier
                        var parent = originalNode.Parent;
                        var leadingTrivia = rewrittenNode.GetLeadingTrivia();
                        rewrittenNode = rewrittenNode.WithLeadingTrivia(null);

                        switch (parent.CSharpKind())
                        {
                            case SyntaxKind.QualifiedName:
                                var qualifiedParent = (QualifiedNameSyntax)parent;

                                result = rewrittenNode.CopyAnnotationsTo(
                                    SyntaxFactory.QualifiedName(
                                        (NameSyntax)left,
                                        (SimpleNameSyntax)rewrittenNode));

                                break;

                            case SyntaxKind.SimpleMemberAccessExpression:
                                var memberAccessParent = (MemberAccessExpressionSyntax)parent;

                                result = rewrittenNode.CopyAnnotationsTo(
                                    SyntaxFactory.MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        left,
                                        (SimpleNameSyntax)rewrittenNode));

                                break;

                            default:
                                Debug.Assert(rewrittenNode is SimpleNameSyntax);

                                if (SyntaxFacts.IsInNamespaceOrTypeContext(originalNode))
                                {
                                    var right = (SimpleNameSyntax)rewrittenNode;
                                    result = rewrittenNode.CopyAnnotationsTo(SyntaxFactory.QualifiedName((NameSyntax)left, right.WithAdditionalAnnotations(Simplifier.SpecialTypeAnnotation)));
                                }
                                else if (originalNode.Parent is CrefSyntax)
                                {
                                    var right = (SimpleNameSyntax)rewrittenNode;
                                    result = rewrittenNode.CopyAnnotationsTo(SyntaxFactory.QualifiedName((NameSyntax)left, right));
                                }
                                else
                                {
                                    result = rewrittenNode.CopyAnnotationsTo(
                                        SyntaxFactory.MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            left,
                                            (SimpleNameSyntax)rewrittenNode));
                                }

                                break;
                        }

                        result = result.WithLeadingTrivia(leadingTrivia);
                    }
                }

                return result;
            }
            private ExpressionSyntax TryAddTypeArgumentToIdentifierName(ExpressionSyntax newNode, ISymbol symbol)
            {
                if (newNode.CSharpKind() == SyntaxKind.IdentifierName && symbol.Kind == SymbolKind.Method)
                {
                    if (((IMethodSymbol)symbol).TypeArguments.Length != 0)
                    {
                        var typeArguments = ((IMethodSymbol)symbol).TypeArguments;

                        var genericName = SyntaxFactory.GenericName(
                                        ((IdentifierNameSyntax)newNode).Identifier,
                                        SyntaxFactory.TypeArgumentList(
                                            SyntaxFactory.SeparatedList(
                                                typeArguments.Select(p => SyntaxFactory.ParseTypeName(p.ToDisplayParts(TypeNameFormatWithGenerics).ToDisplayString())))))
                                        .WithLeadingTrivia(newNode.GetLeadingTrivia())
                                        .WithTrailingTrivia(newNode.GetTrailingTrivia())
                                        .WithAdditionalAnnotations(Simplifier.Annotation);

                        genericName = newNode.CopyAnnotationsTo(genericName);
                        return genericName;
                    }
                }

                return newNode;
            }