public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { var unit = root as CompilationUnitSyntax; var removingUsings = new List <UsingDirectiveSyntax>(); foreach (var u in unit.Usings) { try { if (u.StaticKeyword.RawKind == (int)SyntaxKind.StaticKeyword) { removingUsings.Add(u); } } catch (Exception e) { throw new ReplacerException(u, e); } } return(root.RemoveNodes(removingUsings, SyntaxRemoveOptions.KeepDirectives)); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { root = InsertVariables(root, model); return(ReplacePatterns(root, model)); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { var assignments = root.DescendantNodes().OfType <AssignmentExpressionSyntax>(); var updatedBlocks = new Dictionary <BlockSyntax, List <StatementSyntax> >(); var locals = new List <LocalDeclarationStatementSyntax>(); foreach (var assignment in assignments) { try { if (assignment.Left is IdentifierNameSyntax identifier) { var local = assignment.GetParent <LocalDeclarationStatementSyntax>(); if (local != null && locals.Contains(local)) { continue; } locals.Add(local); var name = identifier.Identifier.ValueText; if (local != null && local.Declaration.Variables.Any(v => v.Identifier.ValueText == name)) { var block = local.Ancestors().OfType <BlockSyntax>().First(); var statements = updatedBlocks.ContainsKey(block) ? updatedBlocks[block] : block.Statements.ToList(); var index = statements.IndexOf(local); foreach (var variable in local.Declaration.Variables) { var newLocal = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(local.Declaration.Type.WithoutTrivia(), SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(variable.Identifier.ValueText)))).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")); if (local.Declaration.Variables.First().Equals(variable)) { newLocal = newLocal.WithLeadingTrivia(local.GetLeadingTrivia()); } statements.Insert(index++, newLocal); if (variable.Initializer != null) { var equals = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(variable.Identifier.ValueText), variable.Initializer.Value.WithoutTrivia())).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")); if (local.Declaration.Variables.Last().Equals(variable)) { equals = equals.WithTrailingTrivia(local.GetTrailingTrivia()); } statements.Insert(index++, equals); } } statements.Remove(local); updatedBlocks[block] = statements; } } } catch (Exception e) { throw new ReplacerException(assignment, e); } } if (updatedBlocks.Count > 0) { root = root.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => b1.WithStatements(SyntaxFactory.List(updatedBlocks[b1]))); } return(root); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater, SharpSixRewriter rewriter) { 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) { var si = model.GetSymbolInfo(arg.Expression); return(si.Symbol == null || si.Symbol is IDiscardSymbol); } 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 is IDiscardSymbol); } return(false); }); var updatedMembers = new Dictionary <MemberAccessExpressionSyntax, string>(); foreach (var memberAccess in root.DescendantNodes().OfType <MemberAccessExpressionSyntax>()) { try { var symbol = model.GetSymbolInfo(memberAccess).Symbol; if (symbol != null && symbol is IFieldSymbol && symbol.ContainingType.IsTupleType) { var field = symbol as IFieldSymbol; var tupleField = field.CorrespondingTupleField; updatedMembers[memberAccess] = tupleField.Name; } } catch (Exception E) { Console.WriteLine(E); } } 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 noLocal = false; var parentTuple = discard.GetParent <TupleExpressionSyntax>(); if (parentTuple != null && parentTuple.Parent is AssignmentExpressionSyntax ae && ae.Left == parentTuple) { noLocal = true; } 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; } } if (!noLocal) { var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discard.Parent.GetLocation().SourceSpan.Start, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList( 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, rewriter)).WithVariables(SyntaxFactory.SingletonSeparatedList( 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) { if (de.Designation is SingleVariableDesignationSyntax designation) { var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, outVar.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(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 annotatedMembers = new Dictionary <SyntaxAnnotation, string>(); var keys = updatedStatements.Keys.Cast <SyntaxNode>() .Concat(updatedDiscards.Keys.Cast <SyntaxNode>()) .Concat(updatedDiscardVars.Keys.Cast <SyntaxNode>()) .Concat(discardAssigments) .Concat(updatedMembers.Keys.Cast <SyntaxNode>()); 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 if (n1 is MemberAccessExpressionSyntax) { annotatedMembers[annotation] = updatedMembers[(MemberAccessExpressionSyntax)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("H5.Script.Discard"))); } outVars = root .DescendantNodes() .OfType <ArgumentSyntax>() .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword); root = root.ReplaceNodes(outVars, (n1, n2) => { if (!(((DeclarationExpressionSyntax)n2.Expression).Designation is SingleVariableDesignationSyntax designation)) { return(n2); } return(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(designation.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).NormalizeWhitespace()); });
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { var localFns = root.DescendantNodes().OfType <LocalFunctionStatementSyntax>(); var updatedBlocks = new Dictionary <SyntaxNode, List <StatementSyntax> >(); var initForBlocks = new Dictionary <SyntaxNode, List <StatementSyntax> >(); var updatedClasses = new Dictionary <TypeDeclarationSyntax, List <DelegateDeclarationSyntax> >(); foreach (var fn in localFns) { try { var parentNode = fn.Parent; var usage = GetFirstUsageLocalFunc(model, fn, parentNode); var beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); if (beforeStatement is LocalFunctionStatementSyntax beforeFn) { List <SyntaxNode> ignore = new List <SyntaxNode>(); var usageFn = usage; var beforeStatementFn = beforeStatement; while (beforeStatementFn != null && beforeStatementFn is LocalFunctionStatementSyntax) { ignore.Add(usageFn); usageFn = GetFirstUsageLocalFunc(model, fn, parentNode, ignore); beforeStatementFn = usageFn?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); } usage = GetFirstUsageLocalFunc(model, beforeFn, parentNode); beforeStatement = usage?.Ancestors().OfType <StatementSyntax>().FirstOrDefault(ss => ss.Parent == parentNode); if (beforeStatementFn != null && (beforeStatement == null || beforeStatementFn.SpanStart < beforeStatement.SpanStart)) { beforeStatement = beforeStatementFn; } } var customDelegate = false; if (fn.TypeParameterList != null && fn.TypeParameterList.Parameters.Count > 0) { customDelegate = true; } else { foreach (var prm in fn.ParameterList.Parameters) { if (prm.Default != null) { customDelegate = true; break; } foreach (var modifier in prm.Modifiers) { var kind = modifier.Kind(); if (kind == SyntaxKind.RefKeyword || kind == SyntaxKind.OutKeyword || kind == SyntaxKind.ParamsKeyword) { customDelegate = true; break; } } if (customDelegate) { break; } } } var returnType = fn.ReturnType.WithoutLeadingTrivia().WithoutTrailingTrivia(); var isVoid = returnType is PredefinedTypeSyntax ptsInstance && ptsInstance.Keyword.Kind() == SyntaxKind.VoidKeyword; TypeSyntax varType; if (customDelegate) { var typeDecl = parentNode.Ancestors().OfType <TypeDeclarationSyntax>().FirstOrDefault(); var delegates = updatedClasses.ContainsKey(typeDecl) ? updatedClasses[typeDecl] : new List <DelegateDeclarationSyntax>(); var name = $"___{fn.Identifier.ValueText}_Delegate_{delegates.Count}"; var delDecl = SyntaxFactory.DelegateDeclaration(returnType, SyntaxFactory.Identifier(name)) .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))) .WithParameterList(fn.ParameterList).NormalizeWhitespace(); delegates.Add(delDecl); updatedClasses[typeDecl] = delegates; varType = SyntaxFactory.IdentifierName(name); } else if (isVoid) { if (fn.ParameterList.Parameters.Count == 0) { varType = SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Action")); } else { varType = SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Action").WithTypeArgumentList ( SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(fn.ParameterList.Parameters.Select(p => p.Type))) ) ); } } else { if (fn.ParameterList.Parameters.Count == 0) { varType = SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Func").WithTypeArgumentList( SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(returnType)) ) ); } else { varType = SyntaxFactory.QualifiedName ( SyntaxFactory.IdentifierName("System"), SyntaxFactory.GenericName("Func").WithTypeArgumentList ( SyntaxFactory.TypeArgumentList( SyntaxFactory.SeparatedList( fn.ParameterList.Parameters.Select(p => p.Type).Concat( new TypeSyntax[] { returnType } ) ) ) ) ); } } List <ParameterSyntax> prms = new List <ParameterSyntax>(); if (customDelegate) { foreach (var prm in fn.ParameterList.Parameters) { var newPrm = prm.WithDefault(null); var idx = newPrm.Modifiers.IndexOf(SyntaxKind.ParamsKeyword); if (idx > -1) { newPrm = newPrm.WithModifiers(newPrm.Modifiers.RemoveAt(idx)); } prms.Add(newPrm); } } else { foreach (var prm in fn.ParameterList.Parameters) { prms.Add(SyntaxFactory.Parameter(prm.Identifier)); } } var initVar = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).WithVariables( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fn.Identifier.ValueText)).WithInitializer ( SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)) ) ) )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE)); var lambda = SyntaxFactory.ParenthesizedLambdaExpression(fn.Body ?? (CSharpSyntaxNode)fn.ExpressionBody.Expression).WithParameterList( SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(prms)) ); if (fn.Modifiers.Any(SyntaxKind.AsyncKeyword)) { lambda = lambda.WithAsyncKeyword(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)); } var assignment = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(fn.Identifier.ValueText), lambda )).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace(Emitter.NEW_LINE)); List <StatementSyntax> statements = null; if (updatedBlocks.ContainsKey(parentNode)) { statements = updatedBlocks[parentNode]; } else { if (parentNode is BlockSyntax bs) { statements = bs.Statements.ToList(); } else if (parentNode is SwitchSectionSyntax sss) { statements = sss.Statements.ToList(); } } var fnIdx = statements.IndexOf(fn); statements.Insert(beforeStatement != null ? statements.IndexOf(beforeStatement) : Math.Max(0, fnIdx), assignment); updatedBlocks[parentNode] = statements; statements = initForBlocks.ContainsKey(parentNode) ? initForBlocks[parentNode] : new List <StatementSyntax>(); statements.Insert(0, initVar); initForBlocks[parentNode] = statements; } catch (Exception e) { throw new ReplacerException(fn, e); } } foreach (var key in initForBlocks.Keys) { updatedBlocks[key] = initForBlocks[key].Concat(updatedBlocks[key]).ToList(); } if (updatedClasses.Count > 0) { root = root.ReplaceNodes(updatedClasses.Keys, (t1, t2) => { var members = updatedClasses[t1].ToArray(); t1 = t1.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => { SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1]))); return(result); }); if (t1 is ClassDeclarationSyntax cls) { return(cls.AddMembers(members)); } if (t2 is StructDeclarationSyntax structDecl) { return(structDecl.AddMembers(members)); } return(t1); }); } else if (updatedBlocks.Count > 0) { root = root.ReplaceNodes(updatedBlocks.Keys, (b1, b2) => { SyntaxNode result = b1 is SwitchSectionSyntax sss ? sss.WithStatements(SyntaxFactory.List(updatedBlocks[b1])) : (SyntaxNode)(((BlockSyntax)b1).WithStatements(SyntaxFactory.List(updatedBlocks[b1]))); return(result); }); } root = root.RemoveNodes(root.DescendantNodes().OfType <LocalFunctionStatementSyntax>(), SyntaxRemoveOptions.KeepTrailingTrivia | SyntaxRemoveOptions.KeepLeadingTrivia); return(root); }
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); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater, SharpSixRewriter rewriter) { root = InsertVariables(root, model, rewriter); var tuple = updater(root); root = tuple.Item1.GetRoot(); model = tuple.Item2; root = ReplaceDeconstructions(root, model); tuple = updater(root); root = tuple.Item1.GetRoot(); model = tuple.Item2; root = ReplaceForeachDeconstructions(root, model); return(root); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, SharpSixRewriter rewriter) { var switches = root.DescendantNodes().OfType <SwitchStatementSyntax>().Where(sw => { return(sw.Sections.Any(s => s.Labels.Any(l => l is CasePatternSwitchLabelSyntax || l is CaseSwitchLabelSyntax csl && csl.Value is CastExpressionSyntax ce && ce.Expression.Kind() == SyntaxKind.DefaultLiteralExpression))); }); var tempKey = 0; root = root.ReplaceNodes(switches, (s1, sw) => { try { var ifNodes = new List <IfStatementSyntax>(); BlockSyntax defaultBlock = null; var isComplex = IsExpressionComplexEnoughToGetATemporaryVariable.IsComplex(model, s1.Expression); var switchExpression = sw.Expression; StatementSyntax switchConditionVariable = null; var iType = model.GetTypeInfo(s1.Expression).Type; var expressionType = SyntaxFactory.ParseTypeName(iType.ToMinimalDisplayString(model, s1.Expression.GetLocation().SourceSpan.Start)); if (isComplex) { var key = tempKey++; var keyArg = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("case_pattern" + key)); var methodIdentifier = SyntaxFactory.IdentifierName("global::H5.Script.ToTemp"); var toTemp = SyntaxFactory.InvocationExpression(methodIdentifier, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(keyArg), SyntaxFactory.Argument(switchExpression) }))); switchConditionVariable = SyntaxFactory.ExpressionStatement(toTemp).NormalizeWhitespace(); var parentMethodIdentifier = SyntaxFactory.GenericName(SyntaxFactory.Identifier("global::H5.Script.FromTemp"), SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(new[] { expressionType }))); switchExpression = SyntaxFactory.InvocationExpression(parentMethodIdentifier, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(keyArg) }))); } foreach (var section in sw.Sections) { // This should catch most (if not all) unhandled yet natively supported syntax usage try { var tuple = CollectCondition(switchExpression, section.Labels, expressionType); var condition = tuple.Item1; var variables = tuple.Item2; var whens = tuple.Item3; var body = SyntaxFactory.Block(); var whenBody = SyntaxFactory.Block(); foreach (var variable in variables) { body = body.WithStatements(body.Statements.Add(SyntaxFactory.LocalDeclarationStatement(variable))); } foreach (var statement in section.Statements) { if (whens.Count > 0) { whenBody = whenBody.WithStatements(whenBody.Statements.Add(statement)); } else { body = body.WithStatements(body.Statements.Add(statement)); } } if (whens.Count > 0) { ExpressionSyntax whenCondition = whens[0]; for (int i = 1; i < whens.Count; ++i) { whenCondition = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, whenCondition, whens[i]); } body = body.WithStatements(body.Statements.Add(SyntaxFactory.IfStatement(whenCondition, whenBody))); } if (condition == null) { defaultBlock = body .WithLeadingTrivia(section.GetLeadingTrivia()) .WithTrailingTrivia(section.GetTrailingTrivia()); break; } ifNodes.Add(SyntaxFactory.IfStatement(condition, body).WithLeadingTrivia(section.GetLeadingTrivia())); } catch (Exception e) { throw new ReplacerException(section, e); } } var doBlock = SyntaxFactory.Block(); if (switchConditionVariable != null) { doBlock = doBlock.WithStatements(doBlock.Statements.Add(switchConditionVariable)); } doBlock = doBlock.WithStatements(doBlock.Statements.AddRange(ifNodes)); if (defaultBlock != null) { doBlock = doBlock.WithStatements(doBlock.Statements.Add(defaultBlock)); } var doStatement = SyntaxFactory.DoStatement(doBlock, SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)); doStatement = doStatement.WithLeadingTrivia(sw.GetLeadingTrivia().Concat(doStatement.GetLeadingTrivia())).WithTrailingTrivia(sw.GetTrailingTrivia()); return(doStatement.NormalizeWhitespace()); } catch (Exception e) { throw new ReplacerException(sw, e); } }); return(root); }
public static GenericNameSyntax GenerateGenericName(SyntaxToken name, IEnumerable <ITypeSymbol> types, SemanticModel model, int pos, SharpSixRewriter rewriter) { return(SyntaxFactory.GenericName(name, SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(types.Select((type) => GenerateTypeSyntax(type, model, pos, rewriter)))))); }
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(GenerateTypeSyntax(el.Type, model, pos, rewriter)); } return(SyntaxFactory.GenericName(SyntaxFactory.Identifier("System.ValueTuple"), SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(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(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 = 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 ) ); } if (model != null) { var ai = model.GetSpeculativeAliasInfo(pos, SyntaxFactory.IdentifierName(gtypeName), SpeculativeBindingOption.BindAsTypeOrNamespace); if (ai != null && ai.Name == gtypeName) { return(SyntaxFactory.ParseTypeName(gtypeName)); } } return(SyntaxFactory.GenericName( SyntaxFactory.Identifier(gtypeName), SyntaxFactory.TypeArgumentList( SyntaxFactory.SeparatedList(types) ) )); } } if (type.ContainingType != null && type.Kind != SymbolKind.TypeParameter) { var parent = 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))); }