コード例 #1
0
        private ExpressionSyntax DeconstructionToMethod(SemanticModel model, ExpressionSyntax tuple, ExpressionSyntax obj, DeconstructionInfo deconstructionInfo)
        {
            List <ArgumentSyntax> arguments = new List <ArgumentSyntax>();

            if (tuple is TupleExpressionSyntax te)
            {
                foreach (var arg in te.Arguments)
                {
                    try
                    {
                        if (arg.Expression is DeclarationExpressionSyntax de)
                        {
                            if (de.Designation is SingleVariableDesignationSyntax sv)
                            {
                                arguments.Add(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(sv.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                                  SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                            }
                        }
                        else
                        {
                            arguments.Add(arg.WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                              SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ReplacerException(arg, e);
                    }
                }
            }
            else
            {
                var variables = ((ParenthesizedVariableDesignationSyntax)((DeclarationExpressionSyntax)tuple).Designation).Variables;
                foreach (var variable in variables)
                {
                    try
                    {
                        if (variable is SingleVariableDesignationSyntax sv)
                        {
                            arguments.Add(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(sv.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(
                                              SyntaxFactory.Token(SyntaxKind.OutKeyword)));
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ReplacerException(variable, e);
                    }
                }
            }

            if (deconstructionInfo.Method != null)
            {
                if (deconstructionInfo.Method.IsExtensionMethod)
                {
                    arguments.Insert(0, SyntaxFactory.Argument(obj));
                    return(SyntaxHelper.GenerateInvocation(deconstructionInfo.Method.Name, deconstructionInfo.Method.ContainingType.FullyQualifiedName(), arguments.ToArray()).NormalizeWhitespace());
                }
                else
                {
                    return(SyntaxHelper.GenerateInvocation(deconstructionInfo.Method.Name, obj, arguments.ToArray()).NormalizeWhitespace());
                }
            }
            else
            {
                arguments.Insert(0, SyntaxFactory.Argument(obj));
                return(SyntaxHelper.GenerateInvocation("Deconstruct", "Bridge.Script", arguments.ToArray()).NormalizeWhitespace());
            }
        }
コード例 #2
0
        public SyntaxNode InsertVariables(SyntaxNode root, SemanticModel model)
        {
            var tuples = root
                         .DescendantNodes()
                         .OfType <TupleExpressionSyntax>()
                         .Where(e => e.Parent is AssignmentExpressionSyntax ae && ae.Left == e || e.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e);

            var updatedStatements = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >();

            foreach (var tuple in tuples)
            {
                try
                {
                    var beforeStatement = tuple.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    if (beforeStatement != null)
                    {
                        foreach (var arg in tuple.Arguments)
                        {
                            if (arg.Expression is DeclarationExpressionSyntax de)
                            {
                                var designation = de.Designation as SingleVariableDesignationSyntax;

                                if (designation != null)
                                {
                                    var locals   = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                    var typeInfo = model.GetTypeInfo(de).Type;
                                    var varDecl  = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo, model, arg.Expression.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                                                                                        SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                                                                                                        ));

                                    locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                    updatedStatements[beforeStatement] = locals;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(tuple, e);
                }
            }

            var parenthesized = root
                                .DescendantNodes()
                                .OfType <ParenthesizedVariableDesignationSyntax>()
                                .Where(e => e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is AssignmentExpressionSyntax ae && ae.Left == e.Parent ||
                                       e.Parent is DeclarationExpressionSyntax && e.Parent.Parent is ForEachVariableStatementSyntax fe && fe.Variable == e.Parent);

            foreach (var p in parenthesized)
            {
                try
                {
                    var beforeStatement = p.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                    var declaration     = (DeclarationExpressionSyntax)p.Parent;
                    if (beforeStatement != null)
                    {
                        var typeInfo            = model.GetTypeInfo(declaration).Type;
                        List <TypeSyntax> types = new List <TypeSyntax>();
                        if (typeInfo.IsTupleType)
                        {
                            var elements = ((INamedTypeSymbol)typeInfo).TupleElements;
                            foreach (var el in elements)
                            {
                                types.Add(SyntaxHelper.GenerateTypeSyntax(el.Type, model, declaration.GetLocation().SourceSpan.Start));
                            }
                        }
                        else
                        {
                            continue;
                        }

                        int idx = 0;
                        foreach (var v in p.Variables)
                        {
                            var designation = v as SingleVariableDesignationSyntax;

                            if (designation != null)
                            {
                                var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();

                                var varDecl = SyntaxFactory.VariableDeclaration(types[idx++]).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                ));

                                locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                updatedStatements[beforeStatement] = locals;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(p, e);
                }
            }

            var annotated = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >();

            root = root.ReplaceNodes(updatedStatements.Keys, (n1, n2) =>
            {
                var annotation        = new SyntaxAnnotation();
                annotated[annotation] = updatedStatements[n1];

                n2 = n2.WithAdditionalAnnotations(annotation);
                return(n2);
            });

            foreach (var annotation in annotated.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var varStatements = annotated[annotation];

                if (annotatedNode is ForEachVariableStatementSyntax fe)
                {
                    varStatements[varStatements.Count - 1] = varStatements.Last().WithAdditionalAnnotations(new SyntaxAnnotation("last_variable"));
                    var list = new List <StatementSyntax>(varStatements);

                    if (fe.Statement is BlockSyntax b)
                    {
                        list.AddRange(b.Statements);
                    }
                    else
                    {
                        list.Add(fe.Statement);
                    }

                    root = root.ReplaceNode(annotatedNode, fe.WithStatement(SyntaxFactory.Block(list)).NormalizeWhitespace());
                }
                else if (annotatedNode.Parent is BlockSyntax || !(annotatedNode is StatementSyntax))
                {
                    root = root.InsertNodesBefore(annotatedNode, varStatements);
                }
                else
                {
                    var list = new List <StatementSyntax>(varStatements);
                    list.Add((StatementSyntax)annotatedNode);
                    root = root.ReplaceNode(annotatedNode, SyntaxFactory.Block(list).NormalizeWhitespace());
                }
            }

            return(root);
        }
コード例 #3
0
ファイル: SyntaxHelper.cs プロジェクト: retsimx/Bridge
        public static string FullyQualifiedName(this ISymbol symbol, bool appenTypeArgs = true)
        {
            var at = symbol as IArrayTypeSymbol;

            if (at != null)
            {
                string result = at.ElementType.FullyQualifiedName() + "[";

                for (int i = 0; i < at.Rank - 1; i++)
                {
                    result += ",";
                }

                result += "]";

                return(result);
            }

            var localName = symbol.Name;

            if (SyntaxHelper.IsCSharpKeyword(localName))
            {
                localName = "@" + localName;
            }

            if (symbol is ITypeParameterSymbol)
            {
                return(localName);
            }

            if (appenTypeArgs)
            {
                if (symbol is INamedTypeSymbol)
                {
                    localName = AppendTypeArguments(localName, ((INamedTypeSymbol)symbol).TypeArguments);
                }
                else if (symbol is IMethodSymbol)
                {
                    localName = AppendTypeArguments(localName, ((IMethodSymbol)symbol).TypeArguments);
                }
            }

            if (symbol.ContainingType != null)
            {
                return(symbol.ContainingType.FullyQualifiedName() + "." + localName);
            }
            else if (symbol.ContainingNamespace != null)
            {
                if (symbol.ContainingNamespace.IsGlobalNamespace)
                {
                    //return "global::" + localName;
                    return(localName);
                }

                return(symbol.ContainingNamespace.FullyQualifiedName() + "." + localName);
            }
            else
            {
                return(localName);
            }
        }
コード例 #4
0
ファイル: SyntaxHelper.cs プロジェクト: retsimx/Bridge
        public static string GetSymbolName(InvocationExpressionSyntax node, SemanticModel semanticModel)
        {
            var si     = semanticModel.GetSymbolInfo(node.ArgumentList.Arguments[0].Expression);
            var symbol = si.Symbol;

            if (symbol == null && si.CandidateSymbols.Any())
            {
                symbol = si.CandidateSymbols.First();
            }

            var name = (string)semanticModel.GetConstantValue(node).Value;

            if (symbol != null && symbol.Kind != SymbolKind.Namespace)
            {
                //bool preserveMemberChange = !(symbol.Kind == SymbolKind.Method || symbol.Kind == SymbolKind.Property);

                int enumMode = -1;

                if (symbol.ContainingType != null && symbol.ContainingType.TypeKind == TypeKind.Enum && symbol is IFieldSymbol)
                {
                    string enumAttr = Translator.Bridge_ASSEMBLY + ".EnumAttribute";
                    enumMode = 7;

                    foreach (var attr in symbol.ContainingType.GetAttributes())
                    {
                        if (attr.AttributeClass != null && attr.AttributeClass.FullyQualifiedName() == enumAttr && attr.ConstructorArguments.Any())
                        {
                            enumMode = (int)attr.ConstructorArguments.First().Value;
                            break;
                        }
                    }
                }

                //if (symbol is IFieldSymbol && ((IFieldSymbol)symbol).IsConst)
                //{
                //    preserveMemberChange = true;
                //}

                var  nameAttr = SyntaxHelper.GetInheritedAttribute(symbol, Bridge.Translator.Translator.Bridge_ASSEMBLY + ".NameAttribute");
                bool isIgnore = symbol.ContainingType != null && SyntaxHelper.IsExternalType(symbol.ContainingType);

                name = symbol.Name;

                if (nameAttr != null)
                {
                    var value = nameAttr.ConstructorArguments.First().Value;
                    if (value is string)
                    {
                        name = value.ToString();
                        if (!isIgnore && symbol.IsStatic && Helpers.IsReservedStaticName(name))
                        {
                            name = Helpers.ChangeReservedWord(name);
                        }
                        return(name);
                    }

                    //preserveMemberChange = !(bool)value;
                    enumMode = -1;
                }

                if (enumMode > 6)
                {
                    switch (enumMode)
                    {
                    case 7:
                        break;

                    case 8:
                        name = name.ToLowerInvariant();
                        break;

                    case 9:
                        name = name.ToUpperInvariant();
                        break;
                    }
                }

                /*else
                 * {
                 *  name = !preserveMemberChange ? Object.Net.Utilities.StringUtils.ToLowerCamelCase(name) : name;
                 * }*/

                if (!isIgnore && symbol.IsStatic && Helpers.IsReservedStaticName(name))
                {
                    name = Helpers.ChangeReservedWord(name);
                }
            }

            return(name);
        }
コード例 #5
0
ファイル: SharpSixRewriter.cs プロジェクト: erhans/Bridge
        private static void ConvertInitializers(SeparatedSyntaxList <ExpressionSyntax> initializers, string instance, List <StatementSyntax> statements, List <InitializerInfo> infos)
        {
            var idx = 0;

            foreach (var init in initializers)
            {
                var info  = infos[idx++];
                var mInfo = info != null && info.method != null ? info.method : null;
                if (mInfo != null)
                {
                    if (mInfo.IsStatic)
                    {
                        var ie = SyntaxHelper.GenerateStaticMethodCall(mInfo.Name,
                                                                       mInfo.ContainingType.FullyQualifiedName(),
                                                                       new[]
                        {
                            SyntaxFactory.Argument(SyntaxFactory.IdentifierName(instance)),
                            SyntaxFactory.Argument(init.WithoutTrivia())
                        }, mInfo.TypeArguments.ToArray());
                        statements.Add(ie);
                    }
                    else
                    {
                        ArgumentSyntax[] arguments = null;
                        if (init.Kind() == SyntaxKind.ComplexElementInitializerExpression)
                        {
                            var complexInit = (InitializerExpressionSyntax)init;

                            arguments = new ArgumentSyntax[complexInit.Expressions.Count];
                            for (int i = 0; i < complexInit.Expressions.Count; i++)
                            {
                                arguments[i] = SyntaxFactory.Argument(complexInit.Expressions[i].WithoutTrivia());
                            }
                        }
                        else
                        {
                            arguments = new[]
                            {
                                SyntaxFactory.Argument(init.WithoutTrivia())
                            };
                        }

                        var ie = SyntaxHelper.GenerateMethodCall(mInfo.Name, instance, arguments, mInfo.TypeArguments.ToArray());
                        statements.Add(ie);
                    }
                }
                else
                {
                    var be = (AssignmentExpressionSyntax)init;

                    if (be.Right is InitializerExpressionSyntax)
                    {
                        string name = null;
                        if (be.Left is IdentifierNameSyntax)
                        {
                            var identifier = (IdentifierNameSyntax)be.Left;
                            name = instance + "." + identifier.Identifier.ValueText;
                        }
                        else if (be.Left is ImplicitElementAccessSyntax)
                        {
                            name = SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName(instance),
                                                                         ((ImplicitElementAccessSyntax)be.Left).ArgumentList.WithoutTrivia()).ToString();
                        }
                        else
                        {
                            name = instance;
                        }

                        SharpSixRewriter.ConvertInitializers(((InitializerExpressionSyntax)be.Right).Expressions, name, statements, info.nested);
                    }
                    else
                    {
                        var indexerKeys = be.Left as ImplicitElementAccessSyntax;

                        if (indexerKeys != null)
                        {
                            be = be.WithLeft(SyntaxFactory.ElementAccessExpression(SyntaxFactory.IdentifierName(instance),
                                                                                   indexerKeys.ArgumentList.WithoutTrivia()));
                        }
                        else
                        {
                            var identifier = (IdentifierNameSyntax)be.Left;
                            be =
                                be.WithLeft(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                 SyntaxFactory.IdentifierName(instance),
                                                                                 SyntaxFactory.IdentifierName(identifier.Identifier.ValueText)));
                        }

                        be = be.WithRight(be.Right.WithoutTrivia());
                        be = be.WithoutTrivia();

                        statements.Add(SyntaxFactory.ExpressionStatement(be, SyntaxFactory.Token(SyntaxKind.SemicolonToken)));
                    }
                }
            }
        }
コード例 #6
0
        public static TypeSyntax GenerateTypeSyntax(ITypeSymbol type, SemanticModel model, int pos, SharpSixRewriter rewriter)
        {
            if (type.IsTupleType)
            {
                var elements = ((INamedTypeSymbol)type).TupleElements;
                var types    = new List <TypeSyntax>();
                foreach (var el in elements)
                {
                    types.Add(SyntaxHelper.GenerateTypeSyntax(el.Type, model, pos, rewriter));
                }

                return(SyntaxFactory.GenericName(SyntaxFactory.Identifier("System.ValueTuple"), SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList <TypeSyntax>(types))));
            }

            var typeName = type.FullyQualifiedName(false);

            if (rewriter.usingStaticNames.Any(n => typeName.StartsWith(n + '.')))
            {
                return(SyntaxFactory.ParseTypeName(type.ToDisplayString()));
            }
            else if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
            {
                var elements = namedType.TypeArguments;
                var types    = new List <TypeSyntax>();
                foreach (var el in elements)
                {
                    types.Add(SyntaxHelper.GenerateTypeSyntax(el, model, pos, rewriter));
                }

                if (type.OriginalDefinition != null && type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
                {
                    return(SyntaxFactory.IdentifierName(type.ToMinimalDisplayString(
                                                            model,
                                                            pos,
                                                            new SymbolDisplayFormat(
                                                                genericsOptions: SymbolDisplayGenericsOptions.None
                                                                )
                                                            )));
                }

                if (types.Count > 0)
                {
                    string gtypeName;
                    if (type.ContainingType != null)
                    {
                        var parent = SyntaxHelper.GenerateTypeSyntax(type.ContainingType, model, pos, rewriter);
                        var name   = type.Name;
                        gtypeName = SyntaxFactory.QualifiedName((NameSyntax)parent, SyntaxFactory.IdentifierName(name)).ToString();
                    }
                    else
                    {
                        gtypeName = type.ToMinimalDisplayString(
                            model,
                            pos,
                            new SymbolDisplayFormat(
                                genericsOptions: SymbolDisplayGenericsOptions.None
                                )
                            );
                    }

                    return(SyntaxFactory.GenericName(
                               SyntaxFactory.Identifier(gtypeName),
                               SyntaxFactory.TypeArgumentList(
                                   SyntaxFactory.SeparatedList <TypeSyntax>(types)
                                   )
                               ));
                }
            }

            if (type.ContainingType != null && type.Kind != SymbolKind.TypeParameter)
            {
                var parent = SyntaxHelper.GenerateTypeSyntax(type.ContainingType, model, pos, rewriter);
                var name   = type.Name;
                return(SyntaxFactory.QualifiedName((NameSyntax)parent, SyntaxFactory.IdentifierName(name)));
            }

            return(SyntaxFactory.ParseTypeName(type.ToMinimalDisplayString(model, pos)));
        }
コード例 #7
0
ファイル: SharpSixRewriter.cs プロジェクト: erhans/Bridge
        public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
        {
            node = (PropertyDeclarationSyntax)base.VisitPropertyDeclaration(node);
            var newNode = node;

            if (node.ExpressionBody != null)
            {
                newNode = SyntaxHelper.ToStatementBody(node);
            }

            if (node.IsAutoProperty() && node.AccessorList != null)
            {
                var setter = node.AccessorList.Accessors.SingleOrDefault(a => a.Keyword.Kind() == SyntaxKind.SetKeyword);

                if (setter == null)
                {
                    var getter = node.AccessorList.Accessors.Single(a => a.Keyword.Kind() == SyntaxKind.GetKeyword);
                    setter = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                             .WithModifiers(SyntaxTokenList.Create(SyntaxFactory.Token(SyntaxKind.PrivateKeyword).WithTrailingTrivia(SyntaxFactory.Space)))
                             .WithBody(null)
                             .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                             .WithLeadingTrivia(getter.GetLeadingTrivia())
                             .WithTrailingTrivia(getter.GetTrailingTrivia());

                    newNode = newNode.AddAccessorListAccessors(setter);
                }

                if (newNode.Initializer != null)
                {
                    var modifiers = SyntaxTokenList.Create(SyntaxFactory.Token(SyntaxKind.PrivateKeyword).WithTrailingTrivia(SyntaxFactory.Space));

                    if (node.Modifiers.Any(m => m.Kind() == SyntaxKind.StaticKeyword))
                    {
                        modifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.StaticKeyword).WithTrailingTrivia(SyntaxFactory.Space));
                    }

                    var field = SyntaxFactory.FieldDeclaration(SyntaxFactory.List <AttributeListSyntax>(),
                                                               modifiers,
                                                               SyntaxFactory.VariableDeclaration(
                                                                   node.Type,
                                                                   SyntaxFactory.SeparatedList(new[] {
                        SyntaxFactory.VariableDeclarator(
                            SyntaxFactory.Identifier(AutoInitFieldPrefix + node.Identifier.Text),
                            null,
                            newNode.Initializer
                            )
                    })
                                                                   ),
                                                               SyntaxFactory.Token(SyntaxKind.SemicolonToken)
                                                               );
                    field = field.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia());
                    fields.Add(field);
                    newNode = newNode.ReplaceNode(newNode.Initializer, (SyntaxNode)null);
                    newNode = SyntaxHelper.RemoveSemicolon(newNode, newNode.SemicolonToken, t => newNode.WithSemicolonToken(t));
                }

                return(newNode);
            }

            return(newNode.Equals(node) ? node : newNode);
        }
コード例 #8
0
ファイル: SharpSixRewriter.cs プロジェクト: erhans/Bridge
        public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
        {
            var symbol = semanticModel.GetSymbolInfo(node).Symbol;

            var parent = node.Parent;

            while (parent != null && !(parent is TypeDeclarationSyntax))
            {
                parent = parent.Parent;
            }

            ITypeSymbol thisType = null;

            if (parent is TypeDeclarationSyntax)
            {
                thisType = this.semanticModel.GetDeclaredSymbol(parent) as ITypeSymbol;
            }

            bool needHandle = !node.IsVar &&
                              symbol is ITypeSymbol &&
                              symbol.ContainingType != null &&
                              thisType != null &&
                              !thisType.InheritsFromOrEquals(symbol.ContainingType) &&
                              !thisType.Equals(symbol);

            var qns = node.Parent as QualifiedNameSyntax;

            if (qns != null && needHandle)
            {
                SyntaxNode n = node;
                do
                {
                    if (!qns.Left.Equals(n))
                    {
                        needHandle = false;
                    }

                    n   = qns;
                    qns = qns.Parent as QualifiedNameSyntax;
                } while (qns != null && needHandle);
            }

            node = (IdentifierNameSyntax)base.VisitIdentifierName(node);

            if (needHandle && !(node.Parent is MemberAccessExpressionSyntax))
            {
                INamedTypeSymbol namedType = symbol as INamedTypeSymbol;
                if (namedType != null && namedType.IsGenericType && namedType.TypeArguments.Length > 0 && !namedType.TypeArguments.Any(SyntaxHelper.IsAnonymous))
                {
                    var genericName = SyntaxHelper.GenerateGenericName(node.Identifier, namedType.TypeArguments);
                    return(genericName.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia()));
                }

                return(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(node.GetLeadingTrivia(), symbol.FullyQualifiedName(), node.GetTrailingTrivia())));
            }

            IMethodSymbol methodSymbol = null;

            if (symbol != null && symbol.IsStatic && symbol.ContainingType != null &&
                thisType != null && !thisType.InheritsFromOrEquals(symbol.ContainingType) &&
                !(node.Parent is MemberAccessExpressionSyntax) &&
                (
                    (methodSymbol = symbol as IMethodSymbol) != null ||
                    symbol is IPropertySymbol ||
                    symbol is IFieldSymbol ||
                    symbol is IEventSymbol)
                )
            {
                if (methodSymbol != null && methodSymbol.IsGenericMethod && methodSymbol.TypeArguments.Length > 0 && !methodSymbol.TypeArguments.Any(SyntaxHelper.IsAnonymous))
                {
                    var genericName = SyntaxHelper.GenerateGenericName(node.Identifier, methodSymbol.TypeArguments);
                    return(genericName.WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia()));
                }

                return(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(node.GetLeadingTrivia(), symbol.FullyQualifiedName(), node.GetTrailingTrivia())));
            }

            return(node);
        }
コード例 #9
0
ファイル: SharpSixRewriter.cs プロジェクト: erhans/Bridge
        public override SyntaxNode VisitArgument(ArgumentSyntax node)
        {
            var ti = this.semanticModel.GetTypeInfo(node.Expression);

            ITypeSymbol      type      = null;
            IMethodSymbol    method    = null;
            IParameterSymbol parameter = null;

            if (ti.Type != null && ti.Type.TypeKind == TypeKind.Delegate)
            {
                type = ti.Type;
            }
            else if (ti.ConvertedType != null && ti.ConvertedType.TypeKind == TypeKind.Delegate)
            {
                type = ti.ConvertedType;
            }

            if (type != null)
            {
                var list       = node.Parent as ArgumentListSyntax;
                var invocation = node.Parent.Parent as InvocationExpressionSyntax;

                if (list != null && invocation != null)
                {
                    method = this.semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;

                    if (method != null)
                    {
                        if (node.NameColon != null)
                        {
                            if (node.NameColon.Name != null)
                            {
                                var nameText = node.NameColon.Name.Identifier.ValueText;
                                if (nameText != null)
                                {
                                    foreach (var p in method.Parameters)
                                    {
                                        if (string.Equals(p.Name, nameText, StringComparison.Ordinal))
                                        {
                                            parameter = p;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            var index = list.Arguments.IndexOf(node);
                            if (index >= 0)
                            {
                                if (index < method.Parameters.Length)
                                {
                                    parameter = method.Parameters[index];
                                }
                                else if (index >= method.Parameters.Length && method.Parameters[method.Parameters.Length - 1].IsParams)
                                {
                                    parameter = method.Parameters[method.Parameters.Length - 1];
                                }
                            }
                        }
                    }
                }
            }
            var isParam = parameter != null && !SyntaxHelper.IsAnonymous(parameter.Type);
            var parent  = isParam && parameter.IsParams ? (InvocationExpressionSyntax)node.Parent.Parent : null;

            node = (ArgumentSyntax)base.VisitArgument(node);

            if (isParam)
            {
                var pType = parameter.Type;
                if (parameter.IsParams && SharpSixRewriter.IsExpandedForm(this.semanticModel, parent, method))
                {
                    pType = ((IArrayTypeSymbol)parameter.Type).ElementType;
                }

                if (node.Expression is CastExpressionSyntax && type.Equals(pType) || parameter.RefKind != RefKind.None)
                {
                    return(node);
                }

                if (pType.TypeKind == TypeKind.Delegate || parameter.IsParams && ((IArrayTypeSymbol)parameter.Type).ElementType.TypeKind == TypeKind.Delegate)
                {
                    var name = SyntaxFactory.IdentifierName(pType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)).WithoutTrivia();
                    var expr = node.Expression;

                    if (expr is LambdaExpressionSyntax || expr is AnonymousMethodExpressionSyntax)
                    {
                        expr = SyntaxFactory.ParenthesizedExpression(expr);
                    }

                    var cast = SyntaxFactory.CastExpression(name, expr);
                    node = node.WithExpression(cast);
                }
            }

            return(node);
        }
コード例 #10
0
ファイル: DiscardReplacer.cs プロジェクト: ultraSsak/Bridge
        public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater)
        {
            var discards = root
                           .DescendantNodes()
                           .OfType <DiscardDesignationSyntax>();

            var outVars = root
                          .DescendantNodes()
                          .OfType <ArgumentSyntax>()
                          .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword);

            var outDiscardVars = root
                                 .DescendantNodes()
                                 .OfType <ArgumentSyntax>()
                                 .Where(arg => {
                if (arg.Expression is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword)
                {
                    var si = model.GetSymbolInfo(arg.Expression);
                    return(si.Symbol == null || si.Symbol.Kind == SymbolKind.Discard);
                }

                return(false);
            });

            var discardAssigments = root
                                    .DescendantNodes()
                                    .OfType <AssignmentExpressionSyntax>()
                                    .Where(assignment => {
                if (assignment.Left is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER)
                {
                    var si = model.GetSymbolInfo(assignment.Left);
                    return(si.Symbol == null || si.Symbol.Kind == SymbolKind.Discard);
                }

                return(false);
            });

            var updatedStatements  = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >();
            var updatedDiscards    = new Dictionary <DiscardDesignationSyntax, string>();
            var updatedDiscardVars = new Dictionary <ArgumentSyntax, string>();

            var tempIndex = 0;

            foreach (var discard in discards)
            {
                try
                {
                    var typeInfo        = model.GetTypeInfo(discard.Parent);
                    var beforeStatement = discard.Ancestors().OfType <StatementSyntax>().FirstOrDefault();

                    if (beforeStatement != null)
                    {
                        if (typeInfo.Type != null)
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                            var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discard.Parent.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                                                                                    SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance))
                                                                                                                                                                                                    ));

                            var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));
                            locals.Add(local);

                            updatedStatements[beforeStatement] = locals;
                            updatedDiscards[discard]           = instance;
                        }
                        else if (discard.Parent is DeclarationPatternSyntax && !(discard.Parent.Parent is IsPatternExpressionSyntax))
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            updatedDiscards[discard] = instance;
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(discard, e);
                }
            }

            foreach (var discardVar in outDiscardVars)
            {
                try
                {
                    var typeInfo = model.GetTypeInfo(discardVar.Expression);

                    if (typeInfo.Type != null)
                    {
                        var beforeStatement = discardVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                        if (beforeStatement != null)
                        {
                            string instance = DISCARD_VARIABLE + ++tempIndex;
                            if (beforeStatement.Parent != null)
                            {
                                var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent);

                                while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                                {
                                    instance = DISCARD_VARIABLE + ++tempIndex;
                                }
                            }

                            var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                            var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discardVar.Expression.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                                                                                           SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance))
                                                                                                                                                                                                           ));

                            var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"));
                            locals.Add(local);

                            updatedStatements[beforeStatement] = locals;
                            updatedDiscardVars[discardVar]     = instance;
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(discardVar, e);
                }
            }

            foreach (var outVar in outVars)
            {
                try
                {
                    if (((DeclarationExpressionSyntax)outVar.Expression).Designation.Kind() == SyntaxKind.DiscardDesignation)
                    {
                        continue;
                    }

                    var typeInfo = model.GetTypeInfo(outVar.Expression);

                    if (typeInfo.Type != null)
                    {
                        var beforeStatement = outVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                        if (beforeStatement != null)
                        {
                            if (outVar.Expression is DeclarationExpressionSyntax de)
                            {
                                var designation = de.Designation as SingleVariableDesignationSyntax;

                                if (designation != null)
                                {
                                    var locals  = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>();
                                    var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, outVar.Expression.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                                                                                                                                                                               SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText))
                                                                                                                                                                                                               ));

                                    locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));

                                    updatedStatements[beforeStatement] = locals;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new ReplacerException(outVar, e);
                }
            }

            var annotatedStatemnts   = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >();
            var annotatedDiscards    = new Dictionary <SyntaxAnnotation, string>();
            var annotatedDiscardVars = new Dictionary <SyntaxAnnotation, string>();
            var annotatedAssigments  = new List <SyntaxAnnotation>();

            var keys = updatedStatements.Keys.Cast <SyntaxNode>()
                       .Concat(updatedDiscards.Keys.Cast <SyntaxNode>())
                       .Concat(updatedDiscardVars.Keys.Cast <SyntaxNode>())
                       .Concat(discardAssigments);

            root = root.ReplaceNodes(keys, (n1, n2) =>
            {
                var annotation = new SyntaxAnnotation();

                if (n1 is AssignmentExpressionSyntax)
                {
                    annotatedAssigments.Add(annotation);
                }
                else if (n1 is DiscardDesignationSyntax)
                {
                    annotatedDiscards[annotation] = updatedDiscards[(DiscardDesignationSyntax)n1];
                }
                else if (n1 is ArgumentSyntax)
                {
                    annotatedDiscardVars[annotation] = updatedDiscardVars[(ArgumentSyntax)n1];
                }
                else
                {
                    annotatedStatemnts[annotation] = updatedStatements[(StatementSyntax)n1];
                }

                n2 = n2.WithAdditionalAnnotations(annotation);
                return(n2);
            });

            foreach (var annotation in annotatedDiscards.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var name          = annotatedDiscards[annotation];

                root = root.ReplaceNode(annotatedNode, SyntaxFactory.SingleVariableDesignation(SyntaxFactory.Identifier(name)).NormalizeWhitespace());
            }

            foreach (var annotation in annotatedDiscardVars.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var name          = annotatedDiscardVars[annotation];

                root = root.ReplaceNode(annotatedNode, ((ArgumentSyntax)annotatedNode).WithExpression(SyntaxFactory.IdentifierName(name)));
            }

            foreach (var annotation in annotatedAssigments)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                root = root.ReplaceNode(annotatedNode, ((AssignmentExpressionSyntax)annotatedNode).WithLeft(SyntaxFactory.IdentifierName("Bridge.Script.Discard")));
            }

            outVars = root
                      .DescendantNodes()
                      .OfType <ArgumentSyntax>()
                      .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword);

            root = root.ReplaceNodes(outVars, (n1, n2) =>
            {
                var designation = ((DeclarationExpressionSyntax)n2.Expression).Designation as SingleVariableDesignationSyntax;

                if (designation == null)
                {
                    return(n2);
                }

                return(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(designation.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).NormalizeWhitespace());
            });

            foreach (var annotation in annotatedStatemnts.Keys)
            {
                var annotatedNode = root.GetAnnotatedNodes(annotation).First();
                var varStatements = annotatedStatemnts[annotation];

                if (annotatedNode.Parent is BlockSyntax || !(annotatedNode is StatementSyntax))
                {
                    root = root.InsertNodesBefore(annotatedNode, varStatements);
                }
                else
                {
                    var list = new List <StatementSyntax>(varStatements);
                    list.Add((StatementSyntax)annotatedNode);
                    root = root.ReplaceNode(annotatedNode, SyntaxFactory.Block(list).NormalizeWhitespace());
                }
            }

            var discardPatterns = root.DescendantNodes().OfType <IsPatternExpressionSyntax>().Where(pattern => pattern.Pattern is DeclarationPatternSyntax dp && dp.Designation.Kind() == SyntaxKind.DiscardDesignation);

            if (discardPatterns.Any())
            {
                root = root.ReplaceNodes(discardPatterns, (n1, n2) => {
                    return(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression, SyntaxFactory.Token(SyntaxKind.TrueKeyword)));
                });
            }

            return(root);
        }
コード例 #11
0
        protected void VisitUnaryOperatorExpression()
        {
            var  unaryOperatorExpression = this.UnaryOperatorExpression;
            var  oldType              = this.Emitter.UnaryOperatorType;
            var  oldAccessor          = this.Emitter.IsUnaryAccessor;
            var  resolveOperator      = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression, this.Emitter);
            var  expectedType         = this.Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression);
            bool isDecimalExpected    = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver);
            bool isDecimal            = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver);
            bool isLongExpected       = Helpers.Is64Type(expectedType, this.Emitter.Resolver);
            bool isLong               = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
            int count = this.Emitter.Writers.Count;

            if (resolveOperator is ConstantResolveResult crr)
            {
                object constantValue = crr.ConstantValue;

                if (unaryOperatorExpression.Operator == UnaryOperatorType.Minus && SyntaxHelper.IsNumeric(constantValue.GetType()) && Convert.ToDouble(constantValue) == 0)
                {
                    this.Write("-");
                }

                this.WriteScript(constantValue);
                return;
            }

            if (Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                this.HandleDecimal(resolveOperator);
                return;
            }

            if (this.ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            if (Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                this.HandleDecimal(resolveOperator, true);
                return;
            }

            if (this.ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            var  op = unaryOperatorExpression.Operator;
            var  argResolverResult = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression, this.Emitter);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);

            if (nullable)
            {
                if (op != UnaryOperatorType.Increment &&
                    op != UnaryOperatorType.Decrement &&
                    op != UnaryOperatorType.PostIncrement &&
                    op != UnaryOperatorType.PostDecrement)
                {
                    this.Write(JS.Types.SYSTEM_NULLABLE + ".");
                }
            }

            bool isAccessor = false;

            var memberArgResolverResult = argResolverResult as MemberResolveResult;

            if (memberArgResolverResult != null)
            {
                var prop = memberArgResolverResult.Member as IProperty;

                if (prop != null)
                {
                    var isIgnore   = memberArgResolverResult.Member.DeclaringTypeDefinition != null && this.Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                    var inlineAttr = prop.Getter != null?this.Emitter.GetAttribute(prop.Getter.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute") : null;

                    var ignoreAccessor     = prop.Getter != null && this.Emitter.Validator.IsExternalType(prop.Getter);
                    var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                    isAccessor = prop.IsIndexer;

                    if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                    {
                        isAccessor = false;
                    }
                }
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            this.Emitter.UnaryOperatorType = op;

            if ((isAccessor) &&
                (op == UnaryOperatorType.Increment ||
                 op == UnaryOperatorType.Decrement ||
                 op == UnaryOperatorType.PostIncrement ||
                 op == UnaryOperatorType.PostDecrement))
            {
                this.Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                    this.Emitter.IsUnaryAccessor = false;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.Emitter.IsUnaryAccessor = true;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" : null)");
                }
                else
                {
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                }

                this.Emitter.IsUnaryAccessor = oldAccessor;

                if (this.Emitter.Writers.Count > count)
                {
                    this.PopWriter();
                }
            }
            else
            {
                switch (op)
                {
                case UnaryOperatorType.BitNot:
                    if (nullable)
                    {
                        this.Write("bnot(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("~");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Decrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        this.Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Increment:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        this.Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Minus:
                    if (nullable)
                    {
                        this.Write("neg(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("-");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Not:
                    if (nullable)
                    {
                        this.Write("not(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("!");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Plus:
                    if (nullable)
                    {
                        this.Write("pos(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }

                    break;

                case UnaryOperatorType.PostDecrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("--");
                        this.Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("--");
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++");
                        this.Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++");
                    }
                    break;

                case UnaryOperatorType.Await:
                    if (this.Emitter.ReplaceAwaiterByVar)
                    {
                        var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1;
                        this.Write(JS.Vars.ASYNC_TASK_RESULT + index);
                    }
                    else
                    {
                        var oldValue = this.Emitter.ReplaceAwaiterByVar;
                        var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling;

                        if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling)
                        {
                            this.WriteAwaiters(unaryOperatorExpression.Expression);
                            this.Emitter.ReplaceAwaiterByVar     = true;
                            this.Emitter.AsyncExpressionHandling = true;
                        }

                        this.WriteAwaiter(unaryOperatorExpression.Expression);

                        this.Emitter.ReplaceAwaiterByVar     = oldValue;
                        this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    }
                    break;

                default:
                    throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString());
                }

                if (this.Emitter.Writers.Count > count)
                {
                    this.PopWriter();
                }
            }

            this.Emitter.UnaryOperatorType = oldType;
        }