private static async Task EditGenericVisitor() { string baseDirectory = Path.GetFullPath( Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), @"..\..\..\..")); LoadedDocumentWithCodeAnalysis document = await LoadedDocumentWithCodeAnalysis.LoadFromFileAsync( Path.Combine(baseDirectory, @"CSharpDom\Common\Expressions\GenericExpressionVisitor.cs")); foreach (StaticClassMethodWithCodeAnalysis method in document.Namespaces.First().Classes.StaticClasses.First().Methods) { IList <IStatementWithCodeAnalysis> statements = method.Body.Statements; if (statements.Count == 1 && statements[0] is ExpressionStatementWithCodeAnalysis expressionStatement && expressionStatement.Expression is MethodCallExpressionWithCodeAnalysis methodCall && methodCall.Expression is MemberExpressionWithCodeAnalysis member && member.ObjectExpression is IdentifierExpressionWithCodeAnalysis identifier && identifier.Name == "GenericExpressionChildVisitor") { continue; } //statements.Clear(); IExpressionWithCodeAnalysis expression = ExpressionFactory.MethodCall( ExpressionFactory.Member(ExpressionFactory.Identifier("GenericChildVisitor"), method.Name)); statements.Add(StatementFactory.Expression(expression)); } }
private static async Task GenerateForwardingVisitor() { string visitorFileName = Path.Combine( Path.GetDirectoryName(typeof(Program).Assembly.Location), @"..\..\..\..\CSharpDom\Common\Statements\GenericStatementChildVisitor.cs"); visitorFileName = Path.GetFullPath(visitorFileName); LoadedDocumentWithCodeAnalysis loadedDocument = await LoadedDocumentWithCodeAnalysis.LoadFromFileAsync(visitorFileName); StaticClassWithCodeAnalysis visitorClass = loadedDocument.Namespaces.First().Classes.StaticClasses.First(); using (CodeAnalysisSettings.AllowEdits(visitorClass)) { foreach (StaticClassMethodWithCodeAnalysis method in visitorClass.Methods.Where(method => method.GenericParameters.LastOrDefault()?.Name != "TVisitor")) { Console.WriteLine($"Editing: {method.Name}"); UnspecifiedTypeReferenceWithCodeAnalysis visitableType = (UnspecifiedTypeReferenceWithCodeAnalysis)method.Parameters[0].ParameterType; InterfaceReferenceWithCodeAnalysis visitorType = new InterfaceReferenceWithCodeAnalysis( "IVisitable", TypeReferenceFactory.GenericParameter("TVisitor")); foreach (GenericParameterDeclarationWithCodeAnalysis genericParameter in method.GenericParameters) { string genericParameterName = genericParameter.Name; if (genericParameterName != "TDocument" && genericParameterName != "TProject" && genericParameterName != "TSolution") { genericParameter.InterfaceConstraints.Add(visitorType); } } string newName = Regex.Replace(visitableType.Name, "^I", "T"); method.Parameters[0].ParameterType = TypeReferenceFactory.GenericParameter(newName); method.Parameters[1].ParameterType = TypeReferenceFactory.GenericParameter("TVisitor"); GenericParameterDeclarationWithCodeAnalysis newGenericParameter = new GenericParameterDeclarationWithCodeAnalysis(newName) { InterfaceConstraints = { new InterfaceReferenceWithCodeAnalysis(visitableType) } }; method.GenericParameters.Insert(0, newGenericParameter); method.GenericParameters.Add(new GenericParameterDeclarationWithCodeAnalysis("TVisitor")); int statementIndex = -1; int parameterIndex = 1; foreach (IStatementWithCodeAnalysis statement in method.Body.Statements) { statementIndex++; if (!(statement is ExpressionStatementWithCodeAnalysis expression) || !(expression.Expression is MethodCallExpressionWithCodeAnalysis methodCall) || !(methodCall.Expression is MemberExpressionWithCodeAnalysis memberCall) || !(memberCall.ObjectExpression is NewExpressionWithCodeAnalysis newObjectCall)) { continue; } UnspecifiedTypeReferenceWithCodeAnalysis type = newObjectCall.Type as UnspecifiedTypeReferenceWithCodeAnalysis; string typeName = type.Name.Replace("Wrapper", string.Empty); string genericTypeName = $"T{typeName}"; string parameterName = $"{typeName.Substring(0, 1).ToLower()}{typeName.Substring(1)}Factory"; newGenericParameter = new GenericParameterDeclarationWithCodeAnalysis(genericTypeName) { InterfaceConstraints = { new InterfaceReferenceWithCodeAnalysis( $"I{typeName}", type.GenericParameters.ToArray()), visitorType } }; method.GenericParameters.Insert(parameterIndex, newGenericParameter); ITypeReferenceWithCodeAnalysis parameterType = TypeReferenceFactory.Delegate( "Func", TypeReferenceFactory.GenericParameter(newName), TypeReferenceFactory.GenericParameter(genericTypeName)); MethodParameterWithCodeAnalysis parameter = new MethodParameterWithCodeAnalysis( parameterType, parameterName); method.Parameters.Insert(parameterIndex, parameter); parameterIndex++; memberCall.ObjectExpression = ExpressionFactory.MethodCall( ExpressionFactory.Identifier(parameterName), ExpressionFactory.Identifier(method.Parameters[0].Name)); } } } const int maximumLineLength = 120; string sourceCode = loadedDocument.ToSourceCode( new IndentMethodParametersIfTooLongRule(maximumLineLength)); File.WriteAllText(visitorFileName, sourceCode); }