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", "H5.Script", arguments.ToArray()).NormalizeWhitespace()); } }
public SyntaxNode InsertVariables(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { 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) { if (de.Designation is SingleVariableDesignationSyntax designation) { 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, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList( 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, rewriter)); } } else { continue; } int idx = 0; foreach (var v in p.Variables) { if (v is SingleVariableDesignationSyntax designation) { var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(types[idx++]).WithVariables(SyntaxFactory.SingletonSeparatedList( 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); }
protected void VisitUnaryOperatorExpression() { var unaryOperatorExpression = UnaryOperatorExpression; var oldType = Emitter.UnaryOperatorType; var oldAccessor = Emitter.IsUnaryAccessor; var resolveOperator = Emitter.Resolver.ResolveNode(unaryOperatorExpression); var expectedType = Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; int count = 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) { Write("-"); } WriteScript(constantValue); return; } if (Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver)) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await) { HandleDecimal(resolveOperator); return; } if (ResolveOperator(unaryOperatorExpression, orr)) { return; } if (Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await) { HandleDecimal(resolveOperator, true); return; } if (ResolveOperator(unaryOperatorExpression, orr)) { return; } var op = unaryOperatorExpression.Operator; var argResolverResult = Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression); bool nullable = NullableType.IsNullable(argResolverResult.Type); if (nullable) { if (op != UnaryOperatorType.Increment && op != UnaryOperatorType.Decrement && op != UnaryOperatorType.PostIncrement && op != UnaryOperatorType.PostDecrement) { Write(JS.Types.SYSTEM_NULLABLE + "."); } } bool isAccessor = false; if (argResolverResult is MemberResolveResult memberArgResolverResult) { if (memberArgResolverResult.Member is IProperty prop) { var isIgnore = memberArgResolverResult.Member.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition); var inlineAttr = prop.Getter != null?Emitter.GetAttribute(prop.Getter.Attributes, Translator.H5_ASSEMBLY + ".TemplateAttribute") : null; var ignoreAccessor = prop.Getter != null && Emitter.Validator.IsExternalType(prop.Getter); var isAccessorsIndexer = 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; } Emitter.UnaryOperatorType = op; if ((isAccessor) && (op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement)) { Emitter.IsUnaryAccessor = true; if (nullable) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); Emitter.IsUnaryAccessor = false; unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(") ? "); Emitter.IsUnaryAccessor = true; unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } Emitter.IsUnaryAccessor = oldAccessor; if (Emitter.Writers.Count > count) { PopWriter(); } } else { switch (op) { case UnaryOperatorType.BitNot: if (nullable) { Write("bnot("); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(")"); } else { Write("~"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.Decrement: if (nullable) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(") ? "); Write("--"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(" : null)"); } else { Write("--"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.Increment: if (nullable) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(") ? "); Write("++"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(" : null)"); } else { Write("++"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.Minus: if (nullable) { Write("neg("); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(")"); } else { Write("-"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.Not: if (nullable) { Write("not("); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(")"); } else { Write("!"); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.Plus: if (nullable) { Write("pos("); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(")"); } else { unaryOperatorExpression.Expression.AcceptVisitor(Emitter); } break; case UnaryOperatorType.PostDecrement: if (nullable) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write("--"); Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write("--"); } break; case UnaryOperatorType.PostIncrement: if (nullable) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write("++"); Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(Emitter); Write("++"); } break; case UnaryOperatorType.Await: if (Emitter.ReplaceAwaiterByVar) { var index = Array.IndexOf(Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1; Write(JS.Vars.ASYNC_TASK_RESULT + index); } else { var oldValue = Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling; if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling) { WriteAwaiters(unaryOperatorExpression.Expression); Emitter.ReplaceAwaiterByVar = true; Emitter.AsyncExpressionHandling = true; } WriteAwaiter(unaryOperatorExpression.Expression); Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; } break; default: throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString()); } if (Emitter.Writers.Count > count) { PopWriter(); } } Emitter.UnaryOperatorType = oldType; }