private static void ProcessType(FxRedist redist, MemberDeclarationSyntax syntax, SemanticModel typeModel, string currentNamespace, ReportWriter reportWriter) { ISymbol symbol = typeModel.GetDeclaredSymbol(syntax); string typeId = symbol.GetDocumentationCommentId(); var typeName = typeId.Substring(2); if (FxdacSyntaxRewriter.s_ShouldRemoveType(typeName)) { reportWriter.WriteListItem("Removed type {0}", symbol.Name); return; } FxAssembly typeAssembly = redist.GetAssemblyForType(typeId); if (typeAssembly.HasEmitedType(typeId)) { return; } // rewrite type var rewriter = new FxdacSyntaxRewriter(reportWriter, typeModel, typeAssembly.Name); syntax = (MemberDeclarationSyntax)syntax.Accept(rewriter); // add type to assembly var typeSyntax = new FxType() { Declaration = syntax, Symbol = (ITypeSymbol)symbol }; typeAssembly.AddType(currentNamespace, typeSyntax); }
static bool CompileAssemblies(FxRedist redist) { bool failed = false; Queue <FxAssembly> toCompile = new Queue <FxAssembly>(redist.Values); List <FxAssembly> sorted = new List <FxAssembly>(); while (toCompile.Count > 0) { var a = toCompile.Dequeue(); if (HasAllDependencies(a, sorted)) { sorted.Add(a); } else { toCompile.Enqueue(a); } } foreach (var a in sorted) { if (HasAllDependencies(a, sorted)) { if (!CompileAssembly(a)) { a.FailedToCompile = true; failed = true; } } } return(!failed); }
private static bool RefactorAssemblies(ReportWriter reportWriter, out FxRedist redist) { // prepare the right folders PrepareOutputFolder(s_OutputSources); PrepareOutputFolder(s_OutputDlls); // load files describing the desired factoring. verify consistency of these files. redist = new FxRedist(); if (!ProcessSpecifications(redist, reportWriter)) { Console.WriteLine("\nPress ENTER to exit ..."); Console.ReadLine(); return(false); } // compile master file reportWriter.WriteListStart("REMOVED"); AddSourcesToRedist(reportWriter, redist, s_MasterAPIFile); AddSourcesToRedist(reportWriter, redist, s_CoreFxAPIFile); reportWriter.WriteListEnd(); // generate and compile factored assemblies GenerateSources(redist); var successfulBuild = CompileAssemblies(redist); // warn about types that are not in any of the factored assemblies if (redist.Leftover.CountOfTypes > 0) { WriteMessage(ConsoleColor.Yellow, "\n{0} type[s] not assigned to an assembly", redist.Leftover.CountOfTypes); } return(successfulBuild); }
private static void AddSourcesToRedist(ReportWriter reportWriter, FxRedist redist, string source) { var parsedSource = CSharpSyntaxTree.ParseText(File.ReadAllText(source)); var compilation = CSharpCompilation.Create("mscorlib", new SyntaxTree[] { parsedSource }); SemanticModel semantic = compilation.GetSemanticModel(parsedSource); // assign roslyn syntax objects (types) to facored assemblies var masterCompilationUnit = parsedSource.GetCompilationUnitRoot(); foreach (var memberSyntax in masterCompilationUnit.Members) { ProcessTypeOrNamespace(redist, memberSyntax, semantic, null, reportWriter); } }
private static bool ProcessSpecification(FxRedist redist, Dictionary <string, string> alreadyLoadedSpecification, string assemblySpecificationFile) { bool success = true; var assembly = new FxAssembly(); assembly.Name = Path.GetFileNameWithoutExtension(assemblySpecificationFile); redist.Add(assembly.Name, assembly); string[] assemblySpecification = File.ReadAllLines(assemblySpecificationFile); Dictionary <string, int> unique = new Dictionary <string, int>(); foreach (var specificationLine in assemblySpecification) { var line = specificationLine.Trim(); if (string.IsNullOrWhiteSpace(line)) { continue; } if (line.StartsWith("//")) { continue; // comment } if (line.StartsWith("/r:")) { assembly.References.Add(line.Substring(3)); continue; } try { unique.Add("T:" + line, 0); try { alreadyLoadedSpecification.Add(line, assemblySpecificationFile); } catch (ArgumentException) { WriteMessage(ConsoleColor.Red, "{0} in files {1} and {2}", line, assemblySpecificationFile, alreadyLoadedSpecification[line]); success = false; } } catch (ArgumentException) { WriteMessage(ConsoleColor.Yellow, "Type {1} duplicated in {0}", assemblySpecificationFile, line); success = false; } } assembly.Types.AddRange(unique.Keys); return(success); }
static void ProcessTypeOrNamespace(FxRedist redist, MemberDeclarationSyntax syntax, SemanticModel typeModel, string currentNamespace, ReportWriter reportWriter) { var namespaceSyntax = syntax as NamespaceDeclarationSyntax; // process all types in namespace if (namespaceSyntax != null) { foreach (var namespaceMember in namespaceSyntax.Members) { string namespaceName = namespaceSyntax.Name.ToString(); ProcessTypeOrNamespace(redist, namespaceMember, typeModel, namespaceName, reportWriter); } return; } ProcessType(redist, syntax, typeModel, currentNamespace, reportWriter); }
static void PrintOrphanedTypes(FxRedist redist, ReportWriter reportWriter) { var assembliesWithOrphanedTypes = redist.Where((a) => a.Value.OrphanedTypes.Count != 0).Select((a) => a.Value).ToList(); if (s_logOrphanedTypes && assembliesWithOrphanedTypes.Count != 0) { reportWriter.WriteListStart("ORPHANED_TYPES", "description", "Orphaned types are types in the specifications that don't exist in master source."); foreach (var assembly in assembliesWithOrphanedTypes) { var orphanedTypes = assembly.OrphanedTypes; WriteMessage(ConsoleColor.Yellow, "Orphaned types in {0}", assembly.Name); foreach (var type in orphanedTypes) { reportWriter.WriteListItem("{0}", type); } } reportWriter.WriteListEnd(); } }
private static void AnalyzeLayers(FxRedist redist, ReportWriter reportWriter) { var assemblies = new List <FxAssembly>(redist.Values); assemblies.Remove(redist.Leftover); Dictionary <int, List <FxAssembly> > layers = new Dictionary <int, List <FxAssembly> >(); int layerNumber = 0; while (assemblies.Count != 0) { var avaliabledependencies = layers.Values.SelectMany((l) => { return(l); }).ToList(); var nextLayer = new List <FxAssembly>(); layers.Add(layerNumber, nextLayer); for (int i = assemblies.Count - 1; i >= 0; i--) { var assembly = assemblies[i]; if (HasAllDependencies(assembly, avaliabledependencies)) { nextLayer.Add(assembly); assemblies.RemoveAt(i); } } layerNumber++; } reportWriter.WriteListStart("Layers"); for (int i = 0; i < layers.Count; i++) { var layer = layers[i]; reportWriter.WriteListStart("Layer", "number", i); foreach (var a in layer) { reportWriter.WriteListItem(a.Name); } reportWriter.WriteListEnd(); } reportWriter.WriteListEnd(); }
static bool ProcessSpecifications(FxRedist redist, ReportWriter reportWriter) { Console.WriteLine("PROCESSING SPECIFICATIONS"); Dictionary <string, string> alreadyLoadedSpecification = new Dictionary <string, string>(); var allFiles = Directory.GetFiles(s_SpecificationFolder); foreach (var assemblySpecificationFile in allFiles) { if (!ProcessSpecification(redist, alreadyLoadedSpecification, assemblySpecificationFile)) { return(false); } } foreach (var a in redist) { foreach (var reference in a.Value.References) { var referenceName = Path.GetFileNameWithoutExtension(reference); if (a.Value.Name == referenceName) { WriteMessage(ConsoleColor.Red, "Assembly {0} references itself.", a.Value.Name); return(false); } if (!redist.Values.Any((a2) => { return(a2.Name == referenceName); })) { WriteMessage(ConsoleColor.Red, "Assembly {0} references {1} that does not exist.", a.Value.Name, reference); return(false); } } } return(true); }
static void GenerateSources(FxRedist assemblies) { foreach (var module in assemblies) { string file = s_OutputSources + "\\" + module.Key + ".cs"; module.Value.SourceFile = file; StreamWriter sw = new StreamWriter(file); sw.WriteLine("[assembly:System.CLSCompliant(true)]"); foreach (var ns in module.Value) { sw.WriteLine("namespace {0} {{", ns.Key); foreach (var type in ns.Value) { if (type.Declaration != null) { sw.Write(type.Declaration.ToFullString()); } } sw.WriteLine("}} // end of {0}", ns.Key); } sw.Close(); } }