Exemple #1
0
        public static async Task <Project> GenerateMocklisClassContents(Project project, CancellationToken cancellationToken = default)
        {
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            if (compilation == null)
            {
                return(project);
            }

            var symbols = new MocklisSymbols(compilation);

            // If we don't reference the right assembly, we could bail early.
            if (symbols.MocklisClassAttribute == null)
            {
                return(project);
            }

            foreach (var documentId in project.DocumentIds)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var document = project.GetDocument(documentId);
                if (document == null || document.SourceCodeKind != SourceCodeKind.Regular)
                {
                    continue;
                }

                var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                var semanticModel = compilation.GetSemanticModel(syntaxTree);
                var emptier       = new MocklisClassEmptier(semanticModel, symbols);

                var syntaxRoot = emptier.Visit(syntaxTree.GetRoot());
                if (!emptier.FoundMocklisClass)
                {
                    continue;
                }

                document   = document.WithSyntaxRoot(syntaxRoot);
                syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var rewriter = new MocklisClassSyntaxRewriter(semanticModel, symbols);

                syntaxRoot = rewriter.Visit(syntaxTree.GetRoot());
                document   = document.WithSyntaxRoot(syntaxRoot);

                var modifiedSpans = syntaxRoot.DescendantNodes().OfType <ClassDeclarationSyntax>().Where(n => n.HasAnnotation(Formatter.Annotation))
                                    .Select(a => a.Span);

                document = await Formatter.FormatAsync(document, modifiedSpans, cancellationToken : cancellationToken).ConfigureAwait(false);

                project = document.Project;
            }

            return(project);
        }
Exemple #2
0
        private async Task <Solution> UpdateMocklisClassAsync(Document document, TypeDeclarationSyntax typeDecl, CancellationToken cancellationToken)
        {
            if (!(typeDecl is ClassDeclarationSyntax classDecl))
            {
                return(document.Project.Solution);
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            MocklisSymbols mocklisSymbols = new MocklisSymbols(semanticModel.Compilation);

            bool isMocklisClass = classDecl.AttributeLists.SelectMany(al => al.Attributes)
                                  .Any(a => semanticModel.GetSymbolInfo(a).Symbol.ContainingType.Equals(mocklisSymbols.MocklisClassAttribute));

            if (!isMocklisClass)
            {
                return(document.Project.Solution);
            }

            var classIsInNullableContext = semanticModel.ClassIsInNullableContext(classDecl);

            var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var emptyClassDecl = MocklisClass.EmptyMocklisClass(classDecl).WithAdditionalAnnotations(new SyntaxAnnotation(MocklisEmptiedClass));
            var emptyRoot      = oldRoot.ReplaceNode(classDecl, emptyClassDecl);
            var emptyDoc       = document.WithSyntaxRoot(emptyRoot);

            emptyRoot = await emptyDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            semanticModel = await emptyDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // And find the class again
            emptyClassDecl = emptyRoot.DescendantNodesAndSelf().OfType <ClassDeclarationSyntax>()
                             .FirstOrDefault(n => n.GetAnnotations(MocklisEmptiedClass).Any());

            if (emptyClassDecl == null)
            {
                return(document.Project.Solution);
            }

            var newClassDecl = MocklisClass.UpdateMocklisClass(semanticModel, emptyClassDecl, mocklisSymbols, classIsInNullableContext);

            var newRoot = emptyRoot.ReplaceNode(emptyClassDecl, newClassDecl);

            return(emptyDoc.WithSyntaxRoot(newRoot).Project.Solution);
        }
Exemple #3
0
 public MocklisClassEmptier(SemanticModel model, MocklisSymbols mocklisSymbols) : base(model, mocklisSymbols)
 {
 }
Exemple #4
0
 public MocklisClassSyntaxRewriter(SemanticModel model, MocklisSymbols mocklisSymbols) : base(model, mocklisSymbols)
 {
 }
Exemple #5
0
 protected MocklisRewriterBase(SemanticModel model, MocklisSymbols mocklisSymbols)
 {
     Model          = model;
     MocklisSymbols = mocklisSymbols;
 }