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

                syntaxWalker.Visit(node);

                return(syntaxWalker.FoundNodes);
            }
Exemple #2
0
            public static SyntaxWalker GetInstance()
            {
                SyntaxWalker walker = _cachedInstance;

                if (walker != null)
                {
                    Debug.Assert(walker.Expressions == null || walker.Expressions.Count == 0);

                    _cachedInstance = null;
                    return(walker);
                }

                return(new SyntaxWalker());
            }
            public static SyntaxWalker GetInstance()
            {
                SyntaxWalker walker = _cachedInstance;

                if (walker != null)
                {
                    _cachedInstance = null;
                    return(walker);
                }
                else
                {
                    return(new SyntaxWalker());
                }
            }
Exemple #4
0
            public static SyntaxWalker GetInstance()
            {
                SyntaxWalker walker = _cachedInstance;

                if (walker != null)
                {
                    Debug.Assert(walker.Parameters.Count == 0);
                    Debug.Assert(walker.SemanticModel == null);
                    Debug.Assert(walker.CancellationToken == default);

                    _cachedInstance = null;
                    return(walker);
                }

                return(new SyntaxWalker());
            }
Exemple #5
0
        private static void AnalyzeBlock(SyntaxNodeAnalysisContext context, BlockSyntax body)
        {
            if (body == null)
            {
                return;
            }

            SyntaxWalker walker = SyntaxWalker.GetInstance();

            walker.VisitBlock(body);

            if (walker.Expressions?.Count > 0)
            {
                foreach (ExpressionSyntax expression in walker.Expressions)
                {
                    ReportDiagnostic(context, expression);
                }
            }

            SyntaxWalker.Free(walker);
        }
        /// <summary>
        /// Run the given visitors on the specified file.
        /// </summary>
        public static void VisitFile(string path, SyntaxWalker[] visitors)
        {
            var tree = SyntaxTree.ParseFile(path);
              var root = (CompilationUnitSyntax)tree.GetRoot();

              foreach (var visitor in visitors)
              {
            visitor.Visit(root);
              }
        }
Exemple #7
0
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxNode declaration,
            ParameterListSyntax parameterList,
            CSharpSyntaxNode bodyOrExpressionBody)
        {
            if (parameterList == null)
            {
                return;
            }

            if (bodyOrExpressionBody == null)
            {
                return;
            }

            if (!parameterList.Parameters.Any())
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(declaration, cancellationToken);

            SyntaxWalker walker = null;

            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
            {
                cancellationToken.ThrowIfCancellationRequested();

                ITypeSymbol type = parameter.Type;

                if (type.Kind == SymbolKind.ErrorType)
                {
                    continue;
                }

                if (CSharpFacts.IsSimpleType(type.SpecialType))
                {
                    continue;
                }

                if (!type.IsReadOnlyStruct())
                {
                    if (parameter.RefKind == RefKind.In &&
                        type.TypeKind == TypeKind.Struct)
                    {
                        var parameterSyntax = (ParameterSyntax)parameter.GetSyntax(cancellationToken);

                        Debug.Assert(parameterSyntax.Modifiers.Contains(SyntaxKind.InKeyword), "");

                        DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.DoNotPassNonReadOnlyStructByReadOnlyReference, parameterSyntax.Identifier);
                    }

                    continue;
                }

                if (parameter.RefKind != RefKind.None)
                {
                    continue;
                }

                if (walker == null)
                {
                    if (methodSymbol.ImplementsInterfaceMember(allInterfaces: true))
                    {
                        break;
                    }

                    walker = SyntaxWalker.GetInstance();
                }
                else if (walker.Parameters.ContainsKey(parameter.Name))
                {
                    walker.Parameters.Clear();
                    break;
                }

                walker.Parameters.Add(parameter.Name, parameter);
            }

            if (walker == null)
            {
                return;
            }

            if (walker.Parameters.Count > 0)
            {
                walker.SemanticModel     = semanticModel;
                walker.CancellationToken = cancellationToken;

                if (bodyOrExpressionBody is BlockSyntax body)
                {
                    walker.VisitBlock(body);
                }
                else
                {
                    walker.VisitArrowExpressionClause((ArrowExpressionClauseSyntax)bodyOrExpressionBody);
                }

                if (walker.Parameters.Count > 0 &&
                    !IsReferencedAsMethodGroup())
                {
                    foreach (KeyValuePair <string, IParameterSymbol> kvp in walker.Parameters)
                    {
                        if (kvp.Value.GetSyntaxOrDefault(cancellationToken) is ParameterSyntax parameter)
                        {
                            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.MakeParameterRefReadOnly, parameter.Identifier);
                        }
                    }
                }
            }

            SyntaxWalker.Free(walker);

            bool IsReferencedAsMethodGroup()
            {
                switch (declaration.Kind())
                {
                case SyntaxKind.MethodDeclaration:
                    return(MethodReferencedAsMethodGroupWalker.IsReferencedAsMethodGroup(declaration.Parent, methodSymbol, semanticModel, cancellationToken));

                case SyntaxKind.LocalFunctionStatement:
                    return(MethodReferencedAsMethodGroupWalker.IsReferencedAsMethodGroup(declaration.FirstAncestor <MemberDeclarationSyntax>(), methodSymbol, semanticModel, cancellationToken));

                default:
                    return(false);
                }
            }
        }
Exemple #8
0
            public static void Free(SyntaxWalker walker)
            {
                walker.Reset();

                _cachedInstance = walker;
            }
Exemple #9
0
            public static void Free(SyntaxWalker walker)
            {
                walker.Expressions?.Clear();

                _cachedInstance = walker;
            }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxNode declaration,
            ParameterListSyntax parameterList,
            CSharpSyntaxNode bodyOrExpressionBody)
        {
            if (parameterList == null)
            {
                return;
            }

            if (bodyOrExpressionBody == null)
            {
                return;
            }

            if (!parameterList.Parameters.Any())
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(declaration, cancellationToken);

            SyntaxWalker walker = null;

            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (parameter.RefKind == RefKind.None)
                {
                    ITypeSymbol type = parameter.Type;

                    //TODO: ITypeSymbol.IsReadOnly, https://github.com/dotnet/roslyn/issues/23792
                    if (type.IsReadOnlyStruct())
                    {
                        if (walker == null)
                        {
                            if (methodSymbol.ImplementsInterfaceMember(allInterfaces: true))
                            {
                                return;
                            }

                            walker = SyntaxWalker.GetInstance();
                        }

                        walker.Parameters.Add(parameter.Name, parameter);
                    }
                }
            }

            if (walker == null)
            {
                return;
            }

            walker.SemanticModel     = semanticModel;
            walker.CancellationToken = cancellationToken;

            if (bodyOrExpressionBody is BlockSyntax body)
            {
                walker.VisitBlock(body);
            }
            else
            {
                walker.VisitArrowExpressionClause((ArrowExpressionClauseSyntax)bodyOrExpressionBody);
            }

            foreach (KeyValuePair <string, IParameterSymbol> kvp in walker.Parameters)
            {
                if (kvp.Value.GetSyntaxOrDefault(cancellationToken) is ParameterSyntax parameter)
                {
                    DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.MakeParameterRefReadOnly, parameter.Identifier);
                }
            }

            SyntaxWalker.Free(walker);
        }
Exemple #11
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}");
                }