public static IEnumerable <SyntaxNode> Find(SyntaxNode node)
            {
                var syntaxWalker = new SyntaxWalker();

                syntaxWalker.Visit(node);

                return(syntaxWalker.FoundNodes);
            }
Ejemplo n.º 2
0
        public void Process()
        {
            // 일단 이 모드에서는 input files만 받는다, output directory는 generated

            // 0. g.cs는 있는데 input이 없는 경우 삭제
            ClearOrphanSources();

            // 1. input은 작업디렉토리에 영향을 받아야 하고, relative만 받는다.. Program.cs A\Sample.cs, FullyQualified면 에러
            var stubTree = GenerateStub();

            var infos = new List <(string OutputFile, SyntaxTree Tree)>();

            foreach (var inputFile in inputFiles)
            {
                if (!VerifyInputFilePath(inputFile))
                {
                    continue;
                }

                string outputFile = MakeOutputFilePath(inputFile);

                var text = fileProvider.ReadAllText(inputFile);
                var tree = CSharpSyntaxTree.ParseText(text);

                infos.Add((outputFile, tree));
            }

            var refs = refAssemblyFiles.Select(refAssemblyFile => MetadataReference.CreateFromFile(refAssemblyFile));

            var compilation = CSharpCompilation.Create(null,
                                                       infos.Select(info => info.Tree).Prepend(stubTree), refs);

            var typeDeclGeneratorsInfo = new Dictionary <TypeDeclarationSyntax, List <IGenerator> >();

            // 1. Collection Phase
            foreach (var tree in infos.Select(info => info.Tree).Prepend(stubTree))
            {
                var model = compilation.GetSemanticModel(tree);

                // type declaration에 대해서 generator들에게 처리할 기회를 준다
                foreach (var typeDecl in tree.GetRoot().DescendantNodes().OfType <TypeDeclarationSyntax>())
                {
                    var relatedGenerators = new List <IGenerator>();
                    foreach (var generator in generators)
                    {
                        // phase2에서 처리할
                        bool bWillGenerateMembers = generator.HandleTypeDecl(typeDecl, model);
                        if (bWillGenerateMembers)
                        {
                            relatedGenerators.Add(generator);
                        }
                    }

                    if (relatedGenerators.Count != 0)
                    {
                        typeDeclGeneratorsInfo.Add(typeDecl, relatedGenerators);
                    }
                }
            }

            // 2. Generation Phase
            foreach (var info in infos)
            {
                var model = compilation.GetSemanticModel(info.Tree);

                var walker = new SyntaxWalker(model, typeDeclGeneratorsInfo);
                walker.Visit(info.Tree.GetRoot());

                if (walker.NeedSave)
                {
                    Debug.Assert(walker.CompilationUnitSyntax != null);
                    SaveOrSkip(info.OutputFile, @$ "#nullable enable

{walker.CompilationUnitSyntax}");
                }