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()); } }
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); }
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); } }
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); }
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))); } } } }
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))); }
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); }
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); }
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); }
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); }
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; }