示例#1
0
        public AbstractLegacyProject(
            string projectSystemName,
            IVsHierarchy hierarchy,
            string language,
            IServiceProvider serviceProvider,
            IThreadingContext threadingContext,
            string externalErrorReportingPrefix,
            HostDiagnosticUpdateSource hostDiagnosticUpdateSourceOpt,
            ICommandLineParserService commandLineParserServiceOpt)
            : base(threadingContext)
        {
            Contract.ThrowIfNull(hierarchy);

            var componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));

            Workspace = componentModel.GetService <VisualStudioWorkspace>();

            var projectFilePath = hierarchy.TryGetProjectFilePath();

            if (projectFilePath != null && !File.Exists(projectFilePath))
            {
                projectFilePath = null;
            }

            if (projectFilePath != null)
            {
                _projectDirectory = Path.GetDirectoryName(projectFilePath);
            }

            var projectFactory = componentModel.GetService <VisualStudioProjectFactory>();

            VisualStudioProject = projectFactory.CreateAndAddToWorkspace(
                projectSystemName,
                language,
                new VisualStudioProjectCreationInfo
            {
                // The workspace requires an assembly name so we can make compilations. We'll use
                // projectSystemName because they'll have a better one eventually.
                AssemblyName = projectSystemName,
                FilePath     = projectFilePath,
                Hierarchy    = hierarchy,
                ProjectGuid  = GetProjectIDGuid(hierarchy),
            });

            ((VisualStudioWorkspaceImpl)Workspace).AddProjectRuleSetFileToInternalMaps(
                VisualStudioProject,
                () => VisualStudioProjectOptionsProcessor.EffectiveRuleSetFilePath);

            // Right now VB doesn't have the concept of "default namespace". But we conjure one in workspace
            // by assigning the value of the project's root namespace to it. So various feature can choose to
            // use it for their own purpose.
            // In the future, we might consider officially exposing "default namespace" for VB project
            // (e.g. through a <defaultnamespace> msbuild property)
            VisualStudioProject.DefaultNamespace = GetRootNamespacePropertyValue(hierarchy);

            Hierarchy = hierarchy;
            ConnectHierarchyEvents();
            RefreshBinOutputPath();

            // TODO: remove this terrible hack, which is working around shims throwing in not-good ways
            try
            {
                _externalErrorReporter  = new ProjectExternalErrorReporter(VisualStudioProject.Id, externalErrorReportingPrefix, Workspace, componentModel.GetService <ExternalErrorDiagnosticUpdateSource>());
                _editAndContinueProject = new VsENCRebuildableProjectImpl(Workspace, VisualStudioProject, serviceProvider);
            }
            catch (Exception)
            {
            }

            _batchScopeCreator = componentModel.GetService <SolutionEventsBatchScopeCreator>();
            _batchScopeCreator.StartTrackingProject(VisualStudioProject, Hierarchy);
        }
示例#2
0
        public AbstractLegacyProject(
            string projectSystemName,
            IVsHierarchy hierarchy,
            string language,
            IServiceProvider serviceProvider,
            IThreadingContext threadingContext,
            string externalErrorReportingPrefix,
            HostDiagnosticUpdateSource hostDiagnosticUpdateSourceOpt,
            ICommandLineParserService commandLineParserServiceOpt)
            : base(threadingContext, assertIsForeground: true)
        {
            Contract.ThrowIfNull(hierarchy);

            var componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));

            Workspace = componentModel.GetService <VisualStudioWorkspace>();
            var workspaceImpl = (VisualStudioWorkspaceImpl)Workspace;

            var projectFilePath = hierarchy.TryGetProjectFilePath();

            if (projectFilePath != null && !File.Exists(projectFilePath))
            {
                projectFilePath = null;
            }

            if (projectFilePath != null)
            {
                _projectDirectory = Path.GetDirectoryName(projectFilePath);
            }

            var projectFactory = componentModel.GetService <VisualStudioProjectFactory>();

            VisualStudioProject = projectFactory.CreateAndAddToWorkspace(
                projectSystemName,
                language,
                new VisualStudioProjectCreationInfo
            {
                // The workspace requires an assembly name so we can make compilations. We'll use
                // projectSystemName because they'll have a better one eventually.
                AssemblyName = projectSystemName,
                FilePath     = projectFilePath,
                Hierarchy    = hierarchy,
                ProjectGuid  = GetProjectIDGuid(hierarchy),
            });

            workspaceImpl.AddProjectRuleSetFileToInternalMaps(
                VisualStudioProject,
                () => VisualStudioProjectOptionsProcessor.EffectiveRuleSetFilePath);

            // Right now VB doesn't have the concept of "default namespace". But we conjure one in workspace
            // by assigning the value of the project's root namespace to it. So various feature can choose to
            // use it for their own purpose.
            // In the future, we might consider officially exposing "default namespace" for VB project
            // (e.g. through a <defaultnamespace> msbuild property)
            VisualStudioProject.DefaultNamespace = GetRootNamespacePropertyValue(hierarchy);

            if (TryGetPropertyValue(hierarchy, AdditionalPropertyNames.MaxSupportedLangVersion, out var maxLangVer))
            {
                VisualStudioProject.MaxLangVersion = maxLangVer;
            }

            if (TryGetBoolPropertyValue(hierarchy, AdditionalPropertyNames.RunAnalyzers, out var runAnayzers))
            {
                VisualStudioProject.RunAnalyzers = runAnayzers;
            }

            if (TryGetBoolPropertyValue(hierarchy, AdditionalPropertyNames.RunAnalyzersDuringLiveAnalysis, out var runAnayzersDuringLiveAnalysis))
            {
                VisualStudioProject.RunAnalyzersDuringLiveAnalysis = runAnayzersDuringLiveAnalysis;
            }

            Hierarchy = hierarchy;
            ConnectHierarchyEvents();
            RefreshBinOutputPath();

            workspaceImpl.SubscribeExternalErrorDiagnosticUpdateSourceToSolutionBuildEvents();

            _externalErrorReporter = new ProjectExternalErrorReporter(VisualStudioProject.Id, externalErrorReportingPrefix, language, workspaceImpl);
            _batchScopeCreator     = componentModel.GetService <SolutionEventsBatchScopeCreator>();
            _batchScopeCreator.StartTrackingProject(VisualStudioProject, Hierarchy);
        }
 // TODO: remove the AllowDefault = true on HostDiagnosticUpdateSource by making it a proper mock
 public VisualStudioProjectFactory(VisualStudioWorkspaceImpl visualStudioWorkspaceImpl, [Import(AllowDefault = true)] HostDiagnosticUpdateSource hostDiagnosticUpdateSource)
 {
     _visualStudioWorkspaceImpl  = visualStudioWorkspaceImpl;
     _hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
 }
示例#4
0
 public VisualStudioAnalyzer(string fullPath, IVsFileChangeEx fileChangeService, HostDiagnosticUpdateSource hostDiagnosticUpdateSource, ProjectId projectId, Workspace workspace, IAnalyzerAssemblyLoader loader, string language)
 {
     _fullPath = fullPath;
     _tracker  = new FileChangeTracker(fileChangeService, fullPath);
     _tracker.UpdatedOnDisk += OnUpdatedOnDisk;
     _tracker.StartFileChangeListeningAsync();
     _tracker.EnsureSubscription();
     _hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
     _projectId = projectId;
     _workspace = workspace;
     _loader    = loader;
     _language  = language;
 }
        // Method is static to prevent accidental use of mutable state in this class
        private static void AnalyzeAndReportConflictsInSolution(
            Solution solution,
            ImmutableHashSet <string> currentAnalyzerPaths,
            HostDiagnosticUpdateSource hostDiagnosticUpdateSource,
            CancellationToken cancellationToken)
        {
            var loadedAssemblies     = AppDomain.CurrentDomain.GetAssemblies().Select(assembly => AssemblyIdentity.FromAssemblyDefinition(assembly));
            var loadedAssembliesList = new IgnorableAssemblyIdentityList(loadedAssemblies);

            var ignorableAssemblyLists = new[] { s_systemPrefixList, s_codeAnalysisPrefixList, s_explicitlyIgnoredAssemblyList, s_assembliesIgnoredByNameList, loadedAssembliesList };

            cancellationToken.ThrowIfCancellationRequested();

            var results = AnalyzerDependencyChecker.ComputeDependencyConflicts(currentAnalyzerPaths, ignorableAssemblyLists, s_bindingRedirectionService, cancellationToken);

            var builder = ImmutableArray.CreateBuilder <DiagnosticData>();

            var conflicts           = results.Conflicts;
            var missingDependencies = results.MissingDependencies;

            foreach (var project in solution.Projects)
            {
                builder.Clear();

                // If our analysis has been cancelled, it means another request has been queued behind us; thus it's OK to stop
                // doing the analysis now and let that other one fix up any stale results.
                cancellationToken.ThrowIfCancellationRequested();

                var analyzerFilePaths = new HashSet <string>(
                    project.AnalyzerReferences
                    .OfType <AnalyzerFileReference>()
                    .Select(f => f.FullPath),
                    StringComparer.OrdinalIgnoreCase);

                foreach (var conflict in conflicts)
                {
                    if (analyzerFilePaths.Contains(conflict.AnalyzerFilePath1) ||
                        analyzerFilePaths.Contains(conflict.AnalyzerFilePath2))
                    {
                        var messageArguments = new string[] { conflict.AnalyzerFilePath1, conflict.AnalyzerFilePath2, conflict.Identity.ToString() };
                        if (DiagnosticData.TryCreate(s_analyzerDependencyConflictRule, messageArguments, project, out var diagnostic))
                        {
                            builder.Add(diagnostic);
                        }
                    }
                }

                foreach (var missingDependency in missingDependencies)
                {
                    if (analyzerFilePaths.Contains(missingDependency.AnalyzerPath))
                    {
                        var messageArguments = new string[] { missingDependency.AnalyzerPath, missingDependency.DependencyIdentity.ToString() };
                        if (DiagnosticData.TryCreate(s_missingAnalyzerReferenceRule, messageArguments, project, out var diagnostic))
                        {
                            builder.Add(diagnostic);
                        }
                    }
                }

                hostDiagnosticUpdateSource.UpdateDiagnosticsForProject(project.Id, s_dependencyConflictErrorId, builder.ToImmutable());
            }

            foreach (var conflict in conflicts)
            {
                LogConflict(conflict);
            }

            foreach (var missingDependency in missingDependencies)
            {
                LogMissingDependency(missingDependency);
            }
        }