예제 #1
0
            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);
            }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
            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));
            }
예제 #5
0
 public CrossArchTreeRewriter(CrossArchSyntaxMap map)
 {
     this.map = map;
 }
예제 #6
0
 public CrossArchSyntaxWalker(CrossArchSyntaxMap map)
 {
     this.map = map;
 }
예제 #7
0
 public CrossArchTreeMerger(CrossArchSyntaxMap map)
 {
     this.map = map;
 }
예제 #8
0
        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));
        }