public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) { var originalName = node.Identifier.ValueText; var name = originalName; HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); if (removeNode) { return(null); } if (name != originalName) { node = node.WithIdentifier(SyntaxFactory.ParseToken(name)); } if (attributeList != null) { node = node.AddAttributeLists(attributeList); } } return(node); }
public static CrossArchSyntaxMap LoadFromTrees(List <SyntaxTree> trees) { CrossArchSyntaxMap map = new CrossArchSyntaxMap(); CrossArchSyntaxWalker walker = new CrossArchSyntaxWalker(map); foreach (var tree in trees) { walker.WalkTree(tree); } return(map); }
public static List <SyntaxTree> MergeTrees(CrossArchSyntaxMap map, List <SyntaxTree> trees) { List <SyntaxTree> ret = new List <SyntaxTree>(); CrossArchTreeRewriter archTreeRewriter = new CrossArchTreeRewriter(map); foreach (var tree in trees) { var fixedTree = archTreeRewriter.ProcessTree(tree); if (fixedTree != null) { ret.Add(fixedTree); } } return(ret); }
public SyntaxTree ProcessTree(SyntaxTree tree) { this.currentArch = CrossArchSyntaxMap.GetArchForTree(tree); if (!CrossArchSyntaxMap.IsCrossArchTree(tree)) { return(tree); } if (this.currentArch == Architecture.None) { return(tree); } var newRoot = (CSharpSyntaxNode)this.Visit(tree.GetRoot()); return(CSharpSyntaxTree.Create(newRoot, null, tree.FilePath)); }
public CrossArchTreeRewriter(CrossArchSyntaxMap map) { this.map = map; }
public CrossArchSyntaxWalker(CrossArchSyntaxMap map) { this.map = map; }
public CrossArchTreeMerger(CrossArchSyntaxMap map) { this.map = map; }
public static ClangSharpSourceCompilation Create( string sourceDirectory, string arch, string interopFileName, Dictionary <string, string> remaps, Dictionary <string, Dictionary <string, string> > enumAdditions, IEnumerable <string> enumsMakeFlags, Dictionary <string, string> typeImports, Dictionary <string, string> requiredNamespaces, HashSet <string> reducePointerLevels, IEnumerable <string> addedRefs) { sourceDirectory = Path.GetFullPath(sourceDirectory); var netstandardPath = FindNetstandardDllPath(); if (!File.Exists(netstandardPath)) { throw new FileNotFoundException("Failed to find the netstandard DLL."); } List <MetadataReference> refs = new List <MetadataReference>(); refs.Add(MetadataReference.CreateFromFile(interopFileName)); refs.Add(MetadataReference.CreateFromFile(netstandardPath)); if (addedRefs != null) { foreach (var r in addedRefs) { refs.Add(MetadataReference.CreateFromFile(r)); } } List <SyntaxTree> syntaxTrees = new List <SyntaxTree>(); var sourceFiles = Directory.GetFiles(sourceDirectory, "*.cs", SearchOption.AllDirectories).Where(f => IsValidCsSourceFile(f, arch)); System.Threading.Tasks.ParallelOptions opt = new System.Threading.Tasks.ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }; System.Threading.Tasks.Parallel.ForEach(sourceFiles, opt, (sourceFile) => { string fileToRead = Path.GetFullPath(sourceFile); var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(fileToRead), null, fileToRead); lock (syntaxTrees) { syntaxTrees.Add(tree); } }); syntaxTrees = NamesToCorrectNamespacesMover.MoveNamesToCorrectNamespaces(syntaxTrees, requiredNamespaces); GetTreeInfo(syntaxTrees, out var emptyStucts, out var enumMemberNames); #if MakeSingleThreaded opt.MaxDegreeOfParallelism = 1; #endif string objDir = Path.Combine(sourceDirectory, $"obj\\{arch}"); Directory.CreateDirectory(objDir); HashSet <string> enumsMakeFlagsHashSet = enumsMakeFlags != null ? new HashSet <string>(enumsMakeFlags) : new HashSet <string>(); List <SyntaxTree> cleanedTrees = new List <SyntaxTree>(); System.Threading.Tasks.Parallel.ForEach(syntaxTrees, opt, (tree) => { // Turn c:\dir\generated\foo.cs into c:\dir\generated\obj\foo.modified.cs string modifiedFile = Path.ChangeExtension(tree.FilePath, ".modified.cs"); string fileWithSubDir = modifiedFile.Substring(sourceDirectory.Length); if (fileWithSubDir.StartsWith('\\')) { fileWithSubDir = fileWithSubDir.Substring(1); } modifiedFile = Path.Combine(objDir, fileWithSubDir); // e.g. c:\dir\generated\obj string newSubDir = Path.GetDirectoryName(modifiedFile); if (!Directory.Exists(newSubDir)) { Directory.CreateDirectory(newSubDir); } var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, emptyStucts, enumMemberNames, modifiedFile); lock (cleanedTrees) { cleanedTrees.Add(cleanedTree); } }); if (arch == "crossarch") { CrossArchSyntaxMap crossArchSyntaxMap = CrossArchSyntaxMap.LoadFromTrees(cleanedTrees); cleanedTrees = CrossArchTreeMerger.MergeTrees(crossArchSyntaxMap, cleanedTrees); } foreach (var cleanedTree in cleanedTrees) { File.WriteAllText(cleanedTree.FilePath, cleanedTree.GetText().ToString()); } CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(OutputKind.WindowsRuntimeMetadata, allowUnsafe: true); var comp = CSharpCompilation.Create( null, cleanedTrees, refs, compilationOptions); return(new ClangSharpSourceCompilation(comp, typeImports)); }