Ejemplo n.º 1
0
        private static async Task FormatProjectAsync(Project project, CodeFormatterOptions options, CancellationToken cancellationToken)
        {
            Solution solution = project.Solution;

            string solutionDirectory = Path.GetDirectoryName(solution.FilePath);

            WriteLine($"  Analyze '{project.Name}'", Verbosity.Minimal);

            SyntaxFactsService syntaxFacts = SyntaxFactsServiceFactory.Instance.GetService(project.Language);

            Project newProject = await CodeFormatter.FormatProjectAsync(project, syntaxFacts, options, cancellationToken);

            ImmutableArray <DocumentId> formattedDocuments = await CodeFormatter.GetFormattedDocumentsAsync(project, newProject, syntaxFacts);

            WriteFormattedDocuments(formattedDocuments, project, solutionDirectory);

            if (formattedDocuments.Length > 0)
            {
                Solution newSolution = newProject.Solution;

                WriteLine($"Apply changes to solution '{newSolution.FilePath}'", Verbosity.Normal);

                if (!solution.Workspace.TryApplyChanges(newSolution))
                {
                    Debug.Fail($"Cannot apply changes to solution '{newSolution.FilePath}'");
                    WriteLine($"Cannot apply changes to solution '{newSolution.FilePath}'", ConsoleColor.Yellow, Verbosity.Diagnostic);
                }
            }

            WriteLine();
            WriteLine($"{formattedDocuments.Length} {((formattedDocuments.Length == 1) ? "document" : "documents")} formatted", ConsoleColor.Green, Verbosity.Normal);
            WriteLine();
        }
Ejemplo n.º 2
0
        internal static async Task <ImmutableArray <DocumentId> > GetFormattedDocumentsAsync(
            Project project,
            Project newProject,
            SyntaxFactsService syntaxFacts)
        {
            ImmutableArray <DocumentId> .Builder builder = null;

            foreach (DocumentId documentId in newProject
                     .GetChanges(project)
                     .GetChangedDocuments(onlyGetDocumentsWithTextChanges: true))
            {
                Document document = newProject.GetDocument(documentId);

                // https://github.com/dotnet/roslyn/issues/30674
                if ((await document.GetTextChangesAsync(project.GetDocument(documentId)).ConfigureAwait(false)).Any())
                {
#if DEBUG
                    bool success = await Utilities.VerifySyntaxEquivalenceAsync(project.GetDocument(document.Id), document, syntaxFacts).ConfigureAwait(false);
#endif
                    (builder ?? (builder = ImmutableArray.CreateBuilder <DocumentId>())).Add(document.Id);
                }
            }

            return(builder?.ToImmutableArray() ?? ImmutableArray <DocumentId> .Empty);
        }
Ejemplo n.º 3
0
        public static async Task <Project> FormatProjectAsync(
            Project project,
            SyntaxFactsService syntaxFacts,
            CodeFormatterOptions options,
            CancellationToken cancellationToken = default)
        {
            if (options == null)
            {
                options = CodeFormatterOptions.Default;
            }

            foreach (DocumentId documentId in project.DocumentIds)
            {
                Document document = project.GetDocument(documentId);

                if (options.IncludeGeneratedCode ||
                    !GeneratedCodeUtility.IsGeneratedCodeFile(document.FilePath))
                {
                    SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                    if (options.IncludeGeneratedCode ||
                        !syntaxFacts.BeginsWithAutoGeneratedComment(root))
                    {
                        DocumentOptionSet optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                        Document newDocument = await Formatter.FormatAsync(document, optionSet, cancellationToken).ConfigureAwait(false);

                        project = newDocument.Project;
                    }
                }
            }

            return(project);
        }
Ejemplo n.º 4
0
 public static Task <Project> FormatProjectAsync(
     Project project,
     SyntaxFactsService syntaxFacts,
     CancellationToken cancellationToken = default)
 {
     return(FormatProjectAsync(project, syntaxFacts, default(CodeFormatterOptions), cancellationToken));
 }
Ejemplo n.º 5
0
        private async Task FormatSolutionAsync(Solution solution, CodeFormatterOptions options, CancellationToken cancellationToken)
        {
            string solutionDirectory = Path.GetDirectoryName(solution.FilePath);

            WriteLine($"Analyze solution '{solution.FilePath}'", ConsoleColor.Cyan, Verbosity.Minimal);

            Stopwatch stopwatch = Stopwatch.StartNew();

            var changedDocuments = new ConcurrentBag <ImmutableArray <DocumentId> >();

            Parallel.ForEach(FilterProjects(solution, Options), project =>
            {
                WriteLine($"  Analyze '{project.Name}'", Verbosity.Minimal);

                SyntaxFactsService syntaxFacts = SyntaxFactsServiceFactory.Instance.GetService(project.Language);

                Project newProject = CodeFormatter.FormatProjectAsync(project, syntaxFacts, options, cancellationToken).Result;

                ImmutableArray <DocumentId> formattedDocuments = CodeFormatter.GetFormattedDocumentsAsync(project, newProject, syntaxFacts).Result;

                if (formattedDocuments.Any())
                {
                    changedDocuments.Add(formattedDocuments);
                    WriteFormattedDocuments(formattedDocuments, project, solutionDirectory);
                }

                WriteLine($"  Done analyzing '{project.Name}'", Verbosity.Normal);
            });

            if (changedDocuments.Count > 0)
            {
                Solution newSolution = solution;

                foreach (DocumentId documentId in changedDocuments.SelectMany(f => f))
                {
                    SourceText sourceText = await solution.GetDocument(documentId).GetTextAsync(cancellationToken);

                    newSolution = newSolution.WithDocumentText(documentId, sourceText);
                }

                WriteLine($"Apply changes to solution '{solution.FilePath}'", Verbosity.Normal);

                if (!solution.Workspace.TryApplyChanges(newSolution))
                {
                    Debug.Fail($"Cannot apply changes to solution '{solution.FilePath}'");
                    WriteLine($"Cannot apply changes to solution '{solution.FilePath}'", ConsoleColor.Yellow, Verbosity.Diagnostic);
                }
            }

            WriteLine();
            WriteLine($"{changedDocuments.Count} {((changedDocuments.Count == 1) ? "document" : "documents")} formatted", ConsoleColor.Green, Verbosity.Normal);
            WriteLine();

            WriteLine($"Done formatting solution '{solution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal);
        }
Ejemplo n.º 6
0
        internal EnvDTE.CodeElement CodeElementFromPosition(int position, EnvDTE.vsCMElement scope)
        {
            var root       = GetSyntaxRoot();
            var leftToken  = SyntaxFactsService.FindTokenOnLeftOfPosition(root, position);
            var rightToken = SyntaxFactsService.FindTokenOnRightOfPosition(root, position);

            // We apply a set of heuristics to determine which member we pick to start searching.
            var token = leftToken;

            if (leftToken != rightToken)
            {
                if (leftToken.Span.End == position && rightToken.SpanStart == position)
                {
                    // If both tokens are touching, we prefer identifiers and keywords to
                    // separators. Note that the language doesn't allow both tokens to be a
                    // keyword or identifier.
                    if (SyntaxFactsService.IsKeyword(rightToken) ||
                        SyntaxFactsService.IsIdentifier(rightToken))
                    {
                        token = rightToken;
                    }
                }
                else if (leftToken.Span.End < position && rightToken.SpanStart <= position)
                {
                    // If only the right token is touching, we have to use it.
                    token = rightToken;
                }
            }

            // If we ended up using the left token but the position is after that token,
            // walk up to the first node who's last token is not the leftToken. By doing this, we
            // ensure that we don't find members when the position is actually between them.
            // In that case, we should find the enclosing type or namespace.
            var parent = token.Parent;

            if (token == leftToken && position > token.Span.End)
            {
                while (parent != null)
                {
                    if (parent.GetLastToken() == token)
                    {
                        parent = parent.Parent;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            var node = parent != null
                ? parent.AncestorsAndSelf().FirstOrDefault(n => CodeModelService.MatchesScope(n, scope))
                : null;

            if (node == null)
            {
                return(null);
            }

            if (scope == EnvDTE.vsCMElement.vsCMElementAttribute ||
                scope == EnvDTE.vsCMElement.vsCMElementImportStmt ||
                scope == EnvDTE.vsCMElement.vsCMElementParameter ||
                scope == EnvDTE.vsCMElement.vsCMElementOptionStmt ||
                scope == EnvDTE.vsCMElement.vsCMElementInheritsStmt ||
                scope == EnvDTE.vsCMElement.vsCMElementImplementsStmt ||
                (scope == EnvDTE.vsCMElement.vsCMElementFunction && CodeModelService.IsAccessorNode(node)))
            {
                // Attributes, imports, parameters, Option, Inherts and Implements
                // don't have node keys of their own and won't be included in our
                // collection of elements. Delegate to the service to create these.
                return(CodeModelService.CreateInternalCodeElement(State, this, node));
            }

            return(CreateCodeElement <EnvDTE.CodeElement>(node));
        }
Ejemplo n.º 7
0
 public bool IsValidID(string name)
 {
     return(SyntaxFactsService.IsValidIdentifier(name));
 }
Ejemplo n.º 8
0
 public bool IsValidID(string name)
 => SyntaxFactsService.IsValidIdentifier(name);