Beispiel #1
0
        public IDocumentOptionsProvider?TryCreate(Workspace workspace)
        {
            if (EditorConfigDocumentOptionsProviderFactory.ShouldUseNativeEditorConfigSupport(workspace))
            {
                // If the native support exists, then we'll simply disable this one
                return(null);
            }

            ICodingConventionsManager codingConventionsManager;

            if (workspace.Kind == WorkspaceKind.RemoteWorkspace)
            {
                // If it's the remote workspace, it's our own implementation of the file watcher which is already doesn't have
                // UI thread dependencies.
                codingConventionsManager = _codingConventionsManager;
            }
            else
            {
                // The default file watcher implementation inside Visual Studio accientally depends on the UI thread
                // (sometimes!) when trying to add a watch to a file. This can cause us to deadlock, since our assumption is
                // consumption of a coding convention can be done freely without having to use a JTF-friendly wait.
                // So we'll wrap the standard file watcher with one that defers the file watches until later.
                var deferredFileWatcher = new DeferredFileWatcher(_fileWatcher, _asynchronousOperationListenerProvider);
                codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(deferredFileWatcher);
            }

            return(new LegacyEditorConfigDocumentOptionsProvider(workspace, codingConventionsManager, _asynchronousOperationListenerProvider));
        }
        internal EditorConfigDocumentOptionsProvider(Workspace workspace)
        {
            _codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            workspace.DocumentOpened += Workspace_DocumentOpened;
            workspace.DocumentClosed += Workspace_DocumentClosed;
        }
        internal void InitializeWorker(AnalysisContext context)
        {
            var workspace = new AdhocWorkspace();
            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            context.RegisterSyntaxTreeAction(c => AnalyzeSyntaxTree(c, workspace, codingConventionsManager));
        }
Beispiel #4
0
        internal EditorConfigDocumentOptionsProvider(Workspace workspace)
        {
            _codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();
            _errorLogger = workspace.Services.GetService <IErrorLoggerService>();

            workspace.DocumentOpened += Workspace_DocumentOpened;
            workspace.DocumentClosed += Workspace_DocumentClosed;
        }
Beispiel #5
0
        public static async Task <int> FormatWorkspaceAsync(ILogger logger, string solutionOrProjectPath, bool isSolution, CancellationToken cancellationToken)
        {
            logger.LogInformation(string.Format(Resources.Formatting_code_files_in_workspace_0, solutionOrProjectPath));

            logger.LogTrace(Resources.Loading_workspace);

            var exitCode           = 1;
            var workspaceStopwatch = Stopwatch.StartNew();

            var properties = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                // This property ensures that XAML files will be compiled in the current AppDomain
                // rather than a separate one. Any tasks isolated in AppDomains or tasks that create
                // AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
                { "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
            };

            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            using (var workspace = MSBuildWorkspace.Create(properties))
            {
                workspace.WorkspaceFailed += (s, e) =>
                {
                    if (e.Diagnostic.Kind != WorkspaceDiagnosticKind.Failure)
                    {
                        logger.LogError(e.Diagnostic.Message);
                        logger.LogError(Resources.Unable_to_load_workspace);
                    }
                };

                var projectPath = string.Empty;
                if (isSolution)
                {
                    await workspace.OpenSolutionAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    await workspace.OpenProjectAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);

                    projectPath = solutionOrProjectPath;
                }

                logger.LogTrace(Resources.Workspace_loaded_in_0_ms, workspaceStopwatch.ElapsedMilliseconds);
                workspaceStopwatch.Restart();

                exitCode = await FormatFilesInSolutionAsync(logger, workspace.CurrentSolution, projectPath, codingConventionsManager, cancellationToken).ConfigureAwait(false);

                logger.LogDebug(Resources.Format_complete_in_0_ms, workspaceStopwatch.ElapsedMilliseconds);
            }

            logger.LogInformation(Resources.Format_complete);

            return(exitCode);
        }
        private async Task <OptionSet> GetOptionsAsync(Document document, CancellationToken cancellationToken)
        {
            OptionSet options = CompilerAnalyzerConfigOptions.Empty;

            // The in-IDE workspace supports .editorconfig without special handling. However, the AdhocWorkspace used
            // in testing requires manual handling of .editorconfig.
            if (File.Exists(document.FilePath ?? document.Name))
            {
                var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();
                var codingConventionContext  = await codingConventionsManager.GetConventionContextAsync(document.FilePath ?? document.Name, cancellationToken).ConfigureAwait(false);

                options = ApplyFormattingOptions(options, codingConventionContext);
            }

            return(options);
        }
Beispiel #7
0
        public static async Task <OptionSet> WithEditorConfigOptions(this OptionSet optionSet, string path, ILoggerFactory loggerFactory)
        {
            if (!Path.IsPathRooted(path))
            {
                path = Directory.GetCurrentDirectory();
            }

            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();
            var optionsApplier           = new EditorConfigOptionsApplier(loggerFactory);
            var context = await codingConventionsManager.GetConventionContextAsync(path, CancellationToken.None);

            if (context != null && context.CurrentConventions != null)
            {
                return(optionsApplier.ApplyConventions(optionSet, context.CurrentConventions, LanguageNames.CSharp));
            }


            return(optionSet);
        }
Beispiel #8
0
        public static async Task <WorkspaceFormatResult> FormatWorkspaceAsync(ILogger logger, string solutionOrProjectPath, bool isSolution, bool logAllWorkspaceWarnings, bool saveFormattedFiles, string[] filesToFormat, CancellationToken cancellationToken)
        {
            logger.LogInformation(string.Format(Resources.Formatting_code_files_in_workspace_0, solutionOrProjectPath));

            logger.LogTrace(Resources.Loading_workspace);

            var loggedWarningCount = 0;
            var formatResult       = new WorkspaceFormatResult()
            {
                ExitCode = 1
            };
            var workspaceStopwatch = Stopwatch.StartNew();

            var properties = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                // This property ensures that XAML files will be compiled in the current AppDomain
                // rather than a separate one. Any tasks isolated in AppDomains or tasks that create
                // AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
                { "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
                // This flag is used at restore time to avoid imports from packages changing the inputs to restore,
                // without this it is possible to get different results between the first and second restore.
                { "ExcludeRestorePackageImports", bool.TrueString },
            };

            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            using (var workspace = MSBuildWorkspace.Create(properties))
            {
                workspace.WorkspaceFailed += LogWorkspaceWarnings;

                var projectPath = string.Empty;
                if (isSolution)
                {
                    await workspace.OpenSolutionAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    try
                    {
                        await workspace.OpenProjectAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);

                        projectPath = solutionOrProjectPath;
                    }
                    catch (InvalidOperationException)
                    {
                        logger.LogError(Resources.Could_not_format_0_Format_currently_supports_only_CSharp_and_Visual_Basic_projects, solutionOrProjectPath);
                        return(formatResult);
                    }
                }

                logger.LogTrace(Resources.Workspace_loaded_in_0_ms, workspaceStopwatch.ElapsedMilliseconds);
                workspaceStopwatch.Restart();

                (formatResult.ExitCode, formatResult.FileCount, formatResult.FilesFormatted) = await FormatFilesInWorkspaceAsync(logger, workspace, projectPath, codingConventionsManager, saveFormattedFiles, filesToFormat, cancellationToken).ConfigureAwait(false);

                logger.LogDebug(Resources.Formatted_0_of_1_files_in_2_ms, formatResult.FilesFormatted, formatResult.FileCount, workspaceStopwatch.ElapsedMilliseconds);
            }

            logger.LogInformation(Resources.Format_complete);

            return(formatResult);

            void LogWorkspaceWarnings(object sender, WorkspaceDiagnosticEventArgs args)
            {
                if (args.Diagnostic.Kind == WorkspaceDiagnosticKind.Failure)
                {
                    return;
                }

                logger.LogWarning(args.Diagnostic.Message);

                if (!logAllWorkspaceWarnings)
                {
                    loggedWarningCount++;

                    if (loggedWarningCount == MaxLoggedWorkspaceWarnings)
                    {
                        logger.LogWarning(Resources.Maximum_number_of_workspace_warnings_to_log_has_been_reached_Set_the_verbosity_option_to_the_diagnostic_level_to_see_all_warnings);
                        ((MSBuildWorkspace)sender).WorkspaceFailed -= LogWorkspaceWarnings;
                    }
                }
            }
        }
Beispiel #9
0
        public static async Task <int> FormatWorkspaceAsync(ILogger logger, string solutionOrProjectPath, bool isSolution, bool logAllWorkspaceWarnings, bool saveFormattedFiles, CancellationToken cancellationToken)
        {
            logger.LogInformation(string.Format(Resources.Formatting_code_files_in_workspace_0, solutionOrProjectPath));

            logger.LogTrace(Resources.Loading_workspace);

            var loggedWarningCount = 0;
            var exitCode           = 1;
            var workspaceStopwatch = Stopwatch.StartNew();

            var properties = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                // This property ensures that XAML files will be compiled in the current AppDomain
                // rather than a separate one. Any tasks isolated in AppDomains or tasks that create
                // AppDomains will likely not work due to https://github.com/Microsoft/MSBuildLocator/issues/16.
                { "AlwaysCompileMarkupFilesInSeparateDomain", bool.FalseString },
            };

            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            using (var workspace = MSBuildWorkspace.Create(properties))
            {
                workspace.WorkspaceFailed += LogWorkspaceWarnings;

                var projectPath = string.Empty;
                if (isSolution)
                {
                    await workspace.OpenSolutionAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    await workspace.OpenProjectAsync(solutionOrProjectPath, cancellationToken : cancellationToken).ConfigureAwait(false);

                    projectPath = solutionOrProjectPath;
                }

                logger.LogTrace(Resources.Workspace_loaded_in_0_ms, workspaceStopwatch.ElapsedMilliseconds);
                workspaceStopwatch.Restart();

                int fileCount;
                int filesFormatted;
                (exitCode, fileCount, filesFormatted) = await FormatFilesInWorkspaceAsync(logger, workspace, projectPath, codingConventionsManager, saveFormattedFiles, cancellationToken).ConfigureAwait(false);

                logger.LogDebug(Resources.Formatted_0_of_1_files_in_2_ms, filesFormatted, fileCount, workspaceStopwatch.ElapsedMilliseconds);
            }

            logger.LogInformation(Resources.Format_complete);

            return(exitCode);

            void LogWorkspaceWarnings(object sender, WorkspaceDiagnosticEventArgs args)
            {
                if (args.Diagnostic.Kind == WorkspaceDiagnosticKind.Failure)
                {
                    return;
                }

                logger.LogWarning(args.Diagnostic.Message);

                if (!logAllWorkspaceWarnings)
                {
                    loggedWarningCount++;

                    if (loggedWarningCount == MaxLoggedWorkspaceWarnings)
                    {
                        logger.LogWarning(Resources.Maximum_number_of_workspace_warnings_to_log_has_been_reached_Set_the_verbosity_option_to_the_diagnostic_level_to_see_all_warnings);
                        ((MSBuildWorkspace)sender).WorkspaceFailed -= LogWorkspaceWarnings;
                    }
                }
            }
        }
Beispiel #10
0
        protected override void InitializeWorker(AnalysisContext context)
        {
            var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager();

            context.RegisterSyntaxTreeAction(c => AnalyzeSyntaxTree(c, codingConventionsManager));
        }