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 void EditUsingDirectives( LoadedDocumentWithCodeAnalysis loadedDocument, string namespaceName) { List <UsingDirectiveWithCodeAnalysis> usingDirectives = loadedDocument.UsingDirectives.ToList(); foreach (UsingDirectiveWithCodeAnalysis directive in usingDirectives) { string directiveName = directive.Name; if (directiveName.Contains("CSharpDom.Common.")) { directive.Name = directiveName.Replace("CSharpDom.Common.", "CSharpDom.Common.Editable."); } } if (namespaceName.StartsWith("CSharpDom.Common.")) { UsingDirectiveWithCodeAnalysis usingDirective = new UsingDirectiveWithCodeAnalysis(namespaceName); usingDirectives.Insert( ~usingDirectives.BinarySearch(usingDirective, new NameComparer()), usingDirective); } loadedDocument.UsingDirectives = usingDirectives; }
private async Task TestType(Type type) { string expectedResult = TypeTextProvider.GetTypeText(type); SolutionWithCodeAnalysis solution = SolutionWithCodeAnalysis.GetSolutionForSourceCode(expectedResult); LoadedDocumentWithCodeAnalysis document = await solution.Projects.First().Documents.First().LoadAsync(); string documentText = document.ToSourceCode(); documentText.TrimEnd().Replace("\r", string.Empty).Should().Be(expectedResult.TrimEnd().Replace("\r", string.Empty)); }
private static async Task GenerateWrapperImplementations() { string baseDirectory = Path.GetFullPath( Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), @"..\..\..\..")); SolutionWithCodeAnalysis solution = await SolutionWithCodeAnalysis.OpenAsync( Path.Combine(baseDirectory, @"CSharpDom.sln")); ProjectWithCodeAnalysis project = solution.Projects.First(p => p.Syntax.Name == "CSharpDom"); project.Lock(); foreach (DocumentWithCodeAnalysis document in project.Documents .Where(document => document.FullFilePath.Contains(@"CSharpDom\Wrappers\Internal")) .OrderBy(document => document.FullFilePath)) { document.IsLocked = true; bool isEdited = false; LoadedDocumentWithCodeAnalysis loadedDocument = await document.LoadAsync(); using (CodeAnalysisSettings.AllowEdits(loadedDocument)) { SealedClassWithCodeAnalysis @class = loadedDocument.Namespaces.First().Classes.SealedClasses.FirstOrDefault(); if (@class == null) { continue; } foreach (SealedClassPropertyWithCodeAnalysis property in @class.Properties .Where(property => property.GetAccessor.Body.Statements.FirstOrDefault() is ThrowStatementWithCodeAnalysis) .ToArray()) { isEdited = true; string propertyName = property.Name; string fieldName = propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1); SealedClassFieldWithCodeAnalysis field = new SealedClassFieldWithCodeAnalysis( ClassMemberVisibilityModifier.Private, new DelegateReferenceWithCodeAnalysis("Func", property.PropertyType), fieldName); @class.Fields.Fields.Add(field); IList <IStatementWithCodeAnalysis> statements = property.GetAccessor.Body.Statements; statements.Clear(); statements.Add( StatementFactory.Return(ExpressionFactory.MethodCall(ExpressionFactory.Identifier(fieldName)))); } } if (isEdited) { string sourceCode = loadedDocument.ToSourceCode(); File.WriteAllText(document.FullFilePath, sourceCode); } } }
public static async Task GenerateEditableInterface(DocumentWithCodeAnalysis document) { string filePath = document.FullFilePath; string destinationPath = Path.Combine( Path.GetDirectoryName(filePath).Replace(@"CSharpDom\Common", @"CSharpDom\Common\Editable"), GetNewName(Path.GetFileName(filePath))); if (File.Exists(destinationPath)) { return; } LoadedDocumentWithCodeAnalysis loadedDocument = await document.LoadAsync(); NamespaceWithCodeAnalysis @namespace = loadedDocument.Namespaces.First(); if (@namespace.Interfaces.Count == 0) { return; } Console.WriteLine($"Writing: {Path.GetFileName(destinationPath)}"); string namespaceName = @namespace.Name; using (CodeAnalysisSettings.AllowEdits(loadedDocument)) { EditUsingDirectives(loadedDocument, namespaceName); @namespace.Name = Regex.Replace(namespaceName, "^CSharpDom.Common", "CSharpDom.Common.Editable"); InterfaceWithCodeAnalysis @interface = @namespace.Interfaces.First(); string interfaceName = @interface.Name; @interface.Name = GetNewName(interfaceName); List <ITypeReferenceWithCodeAnalysis> genericParameters = EditInterfaceGenericParameters(@interface); EditInterfaceBaseInterfaces(@interface, interfaceName, genericParameters); EditInterfaceProperties(@interface); } Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); const int maximumLineLength = 120; string sourceCode = loadedDocument.ToSourceCode( new IndentBaseTypeListIfTooLongRule(maximumLineLength), new IndentGenericParamterDefinitionsIfTooLongRule(maximumLineLength), new IndentMethodParametersIfTooLongRule(maximumLineLength)); File.WriteAllText(destinationPath, sourceCode); }
private static async Task LoadImplementInterfaceAsync() { var assembly = Assembly.Load("Microsoft.CodeAnalysis.CSharp.Features"); var configuration = new ContainerConfiguration().WithAssembly(assembly); var container = configuration.CreateContainer(); var test = container.GetExports <CodeFixProvider>().ToArray(); var test2 = test.FirstOrDefault(provider => (Attribute.GetCustomAttribute(provider.GetType(), typeof(ExportCodeFixProviderAttribute)) as ExportCodeFixProviderAttribute)?.Name == "ImplementInterface"); string solutionFile = Path.Combine( Path.GetDirectoryName(typeof(Program).Assembly.Location), @"..\..\..\..\CSharpDom.sln"); solutionFile = Path.GetFullPath(solutionFile); SolutionWithCodeAnalysis solution = await SolutionWithCodeAnalysis.OpenAsync(solutionFile); //(Workspace, ProjectWithCodeAnalysis) project = await ProjectWithCodeAnalysis.OpenWithWorkspaceAsync(projectFile); DocumentWithCodeAnalysis document = solution.Projects .First(project => project.Syntax.Name == "CSharpDom.EditableInterfaceGenerator") .Documents.First(); Compilation compilation = await document.Syntax.Project.GetCompilationAsync(); //SyntaxGenerator generator = document.Syntax.get LoadedDocumentWithCodeAnalysis loadedDocument = await document.LoadAsync(); var syntax = loadedDocument.Namespaces.First().Classes.SealedClasses.First().ImplementedInterfaces.First().Syntax; List <CodeAction> actions = new List <CodeAction>(); var descriptor = new DiagnosticDescriptor("CS0535", "CS0535", "CS0535", "CS0535", DiagnosticSeverity.Error, true); CodeFixContext context = new CodeFixContext( document.Syntax, Diagnostic.Create(descriptor, Location.Create(syntax.SyntaxTree, syntax.Span)), (action, diagnostics) => actions.Add(action), CancellationToken.None); await test2.RegisterCodeFixesAsync(context); var operations = await actions[0].GetOperationsAsync(CancellationToken.None); foreach (var operation in operations) { operation.Apply(solution.Syntax.Workspace, CancellationToken.None); } actions.GetHashCode(); }
internal static PartialClassCollectionWithCodeAnalysis Create(LoadedDocumentWithCodeAnalysis document) { var members = document.Members; var abstractClasses = new LoadedDocumentMemberListWrapper <AbstractPartialClassWithCodeAnalysis, ClassDeclarationSyntax>( document.Node, () => new AbstractPartialClassWithCodeAnalysis(document.Document), ClassDeclarationSyntaxExtensions.IsAbstractPartialClass); var classes = new LoadedDocumentMemberListWrapper <PartialClassWithCodeAnalysis, ClassDeclarationSyntax>( document.Node, () => new PartialClassWithCodeAnalysis(document.Document), ClassDeclarationSyntaxExtensions.IsPartialClass); var sealedClasses = new LoadedDocumentMemberListWrapper <SealedPartialClassWithCodeAnalysis, ClassDeclarationSyntax>( document.Node, () => new SealedPartialClassWithCodeAnalysis(document.Document), ClassDeclarationSyntaxExtensions.IsSealedPartialClass); var staticClasses = new LoadedDocumentMemberListWrapper <StaticPartialClassWithCodeAnalysis, ClassDeclarationSyntax>( document.Node, () => new StaticPartialClassWithCodeAnalysis(document.Document), ClassDeclarationSyntaxExtensions.IsStaticPartialClass); return(new PartialClassCollectionWithCodeAnalysis(members, abstractClasses, classes, sealedClasses, staticClasses)); }
private static async Task GenerateEditableWrappers() { string baseDirectory = Path.GetFullPath( Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), @"..\..\..\..")); ProjectWithCodeAnalysis project = await ProjectWithCodeAnalysis.OpenAsync( Path.Combine(baseDirectory, @"CSharpDom\CSharpDom.csproj")); project.Lock(); foreach (DocumentWithCodeAnalysis document in project.Documents.OrderBy(document => document.FullFilePath)) { document.IsLocked = true; string filePath = document.FullFilePath; if (!filePath.Contains(@"CSharpDom\BaseClasses\Wrappers")) { continue; } string newDirectory = Path.GetDirectoryName(filePath) .Replace(@"CSharpDom\BaseClasses\Wrappers", @"CSharpDom\BaseClasses\Editable\Wrappers"); string destinationPath = Path.Combine(newDirectory, GetNewName(Path.GetFileName(filePath))); if (File.Exists(destinationPath)) { continue; } LoadedDocumentWithCodeAnalysis loadedDocument = await document.LoadAsync(); NamespaceWithCodeAnalysis @namespace = loadedDocument.Namespaces.First(); Console.WriteLine($"Writing: {Path.GetFileName(destinationPath)}"); string namespaceName = @namespace.Name; using (CodeAnalysisSettings.AllowEdits(loadedDocument)) { foreach (UsingDirectiveWithCodeAnalysis directive in loadedDocument.UsingDirectives) { directive.Name = directive.Name.Replace("CSharpDom.Common", "CSharpDom.Common.Editable"); } loadedDocument.UsingDirectives.Add(new UsingDirectiveWithCodeAnalysis("CSharpDom.Common")); loadedDocument.UsingDirectives = loadedDocument.UsingDirectives .OrderBy(directive => directive.Name) .ToArray(); @namespace.Name = "CSharpDom.BaseClasses.Editable.Wrappers"; SealedClassWithCodeAnalysis @class = @namespace.Classes.SealedClasses.First(); @class.Name = "Editable" + @class.Name; @class.BaseClass.Name = Regex.Replace(@class.BaseClass.Name, "^Abstract", "Editable"); ITypeReferenceWithCodeAnalysis interfaceReference = @class.ImplementedInterfaces.First().GenericParameters[0]; interfaceReference.Name = Regex.Replace(interfaceReference.Name, "^I", "IEditable"); foreach (GenericParameterDeclarationWithCodeAnalysis genericParameter in @class.GenericParameters) { InterfaceReferenceWithCodeAnalysis constraint = genericParameter.InterfaceConstraints.First(); constraint.Name = Regex.Replace(constraint.Name, "^I", "IEditable"); } ITypeReferenceWithCodeAnalysis constructorParameterType = @class.Constructors.First().Parameters[0].ParameterType; constructorParameterType.Name = Regex.Replace(constructorParameterType.Name, "^I", "IEditable"); foreach (SealedClassAutoPropertyWithCodeAnalysis property in @class.Properties.AutoProperties) { if (property.Name == "WrappedObject") { //CodeAnalysisLogger.StartLoggingDebugMessages(); property.PropertyType.Name = Regex.Replace(property.PropertyType.Name, "^I", "IEditable"); //string[] logMessages = CodeAnalysisLogger.GetDebugLogMessages(); //CodeAnalysisLogger.StopLoggingDebugMessages(); break; } } foreach (SealedClassPropertyWithCodeAnalysis property in @class.Properties) { string propertyName = property.Name; if (propertyName == "WrappedObject") { continue; } string propertyTypeName = property.PropertyType.Name; if (propertyTypeName.Contains("ReadOnly")) { property.PropertyType.Name = propertyTypeName.Replace("ReadOnly", string.Empty); } IExpressionWithCodeAnalysis expression = ExpressionFactory.Binary( ExpressionFactory.Member(ExpressionFactory.Identifier("WrappedObject"), propertyName), BinaryOperatorExpressionType.Assign, ExpressionFactory.Identifier("value")); property.SetAccessor = new ClassAccessorWithCodeAnalysis( AccessorType.Set, new MethodBodyWithCodeAnalysis(StatementFactory.Expression(expression))); } Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); const int maximumLineLength = 120; string sourceCode = loadedDocument.ToSourceCode( new IndentBaseTypeListIfTooLongRule(maximumLineLength), new IndentGenericParamterDefinitionsIfTooLongRule(maximumLineLength), new IndentMethodParametersIfTooLongRule(maximumLineLength)); File.WriteAllText(destinationPath, sourceCode); } } }
public static async Task GenerateBaseClass(DocumentWithCodeAnalysis document) { string filePath = document.FullFilePath; string destinationPath = Path.Combine( Path.GetDirectoryName(filePath).Replace(@"CSharpDom\Common", @"CSharpDom\BaseClasses"), GetNewName(Path.GetFileName(filePath))); if (File.Exists(destinationPath)) { return; } LoadedDocumentWithCodeAnalysis loadedDocument = await document.LoadAsync(); NamespaceWithCodeAnalysis @namespace = loadedDocument.Namespaces.First(); if (@namespace.Interfaces.Count == 0) { return; } InterfaceWithCodeAnalysis @interface = @namespace.Interfaces.First(); if (@interface.GenericParameters.Count == 0) { return; } Console.WriteLine($"Writing: {Path.GetFileName(destinationPath)}"); string namespaceName = @namespace.Name; using (CodeAnalysisSettings.AllowEdits(loadedDocument)) { LoadedDocumentWithCodeAnalysis newDocument = new LoadedDocumentWithCodeAnalysis(); newDocument.UsingDirectives.Add(new UsingDirectiveWithCodeAnalysis(namespaceName)); DocumentWithCodeAnalysis baseClassDocument = document.Project.AddDocument( destinationPath, newDocument); NamespaceWithCodeAnalysis newNamespace = new NamespaceWithCodeAnalysis( baseClassDocument, namespaceName.Replace("Common", "BaseClasses")); AbstractClassWithCodeAnalysis baseClass = new AbstractClassWithCodeAnalysis( baseClassDocument, TypeVisibilityModifier.Public, GetNewName(@interface.Name)) { GenericParameters = @interface.GenericParameters, BaseClass = new ClassReferenceWithCodeAnalysis("AbstractExpression") }; ITypeReferenceWithCodeAnalysis[] implementedInterfaceGenericParameters = @interface.GenericParameters .Select(parameter => new GenericParameterReferenceWithCodeAnalysis(parameter.Name)) .ToArray(); baseClass.ImplementedInterfaces.Add( new InterfaceReferenceWithCodeAnalysis(@interface.Name, implementedInterfaceGenericParameters)); newNamespace.Classes.AbstractClasses.Add(baseClass); newDocument.Namespaces.Add(newNamespace); await baseClass.ImplementInterfaceAsync(@class => @class.ImplementedInterfaces.First(), baseClassDocument); foreach (AbstractClassPropertyWithCodeAnalysis property in baseClass.Properties) { } } Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); const int maximumLineLength = 120; string sourceCode = loadedDocument.ToSourceCode( new IndentBaseTypeListIfTooLongRule(maximumLineLength), new IndentGenericParamterDefinitionsIfTooLongRule(maximumLineLength), new IndentMethodParametersIfTooLongRule(maximumLineLength)); File.WriteAllText(destinationPath, sourceCode); }
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); }