Example #1
0
        private void ShowInfoBarIfNecessary()
        {
            // Only check for whether we should show an info bar once per session.
            _infoBarChecked = true;
            if (_experimentationService.IsExperimentEnabled(AnalyzerEnabledFlight))
            {
                AnalyzerABTestLogger.Log(nameof(AnalyzerEnabledFlight));

                // If we got true from the experimentation service, then we're in the treatment
                // group, and the experiment is enabled. We determine if the infobar has been
                // displayed in the past 24 hours. If it hasn't been displayed, then we do so now.
                var lastTimeInfoBarShown = DateTime.FromBinary(_workspace.Options.GetOption(AnalyzerABTestOptions.LastDateTimeInfoBarShown));
                var utcNow             = DateTime.UtcNow;
                var timeSinceLastShown = utcNow - lastTimeInfoBarShown;

                if (timeSinceLastShown.TotalDays >= 1)
                {
                    _workspace.Options = _workspace.Options.WithChangedOption(AnalyzerABTestOptions.LastDateTimeInfoBarShown, utcNow.ToBinary());
                    AnalyzerABTestLogger.Log("InfoBarShown");

                    var infoBarService = _workspace.Services.GetRequiredService <IInfoBarService>();
                    infoBarService.ShowInfoBarInGlobalView(
                        ServicesVSResources.Try_the_preview_version_of_our_live_code_analysis_extension_which_provides_more_fixes_for_common_API_design_naming_performance_and_reliability_issues,
                        // Install link
                        new InfoBarUI(title: ServicesVSResources.Learn_more,
                                      kind: InfoBarUI.UIKind.HyperLink,
                                      action: OpenInstallHyperlink),
                        // Don't show the InfoBar again link
                        new InfoBarUI(title: ServicesVSResources.Never_show_this_again,
                                      kind: InfoBarUI.UIKind.Button,
                                      action: DoNotShowAgain));
                }
            }
        }
Example #2
0
        private bool IsCandidate()
        {
            // if this user ever participated in the experiement and then uninstall the vsix, then
            // this user will never be candidate again.
            if (_workspace.Options.GetOption(AnalyzerABTestOptions.ParticipatedInExperiment))
            {
                return(false);
            }

            // Filter for valid A/B test candidates. Candidates fill the following critera:
            //     1: Are a Dotnet user (as evidenced by the fact that this code is being run)
            //     2: Have triggered a lightbulb on 3 separate days

            // If the user hasn't met candidacy conditions, then we check them. Otherwise, proceed
            // to info bar check
            var options     = _workspace.Options;
            var isCandidate = options.GetOption(AnalyzerABTestOptions.HasMetCandidacyRequirements);

            if (!isCandidate)
            {
                // We store in UTC to avoid any timezone offset weirdness
                var lastTriggeredTimeBinary = options.GetOption(AnalyzerABTestOptions.LastDateTimeUsedSuggestionAction);
                AnalyzerABTestLogger.LogCandidacyRequirementsTracking(lastTriggeredTimeBinary);

                var lastTriggeredTime = DateTime.FromBinary(lastTriggeredTimeBinary);
                var currentTime       = DateTime.UtcNow;
                var span = currentTime - lastTriggeredTime;
                if (span.TotalDays >= 1)
                {
                    options = options.WithChangedOption(AnalyzerABTestOptions.LastDateTimeUsedSuggestionAction, currentTime.ToBinary());

                    var usageCount = options.GetOption(AnalyzerABTestOptions.UsedSuggestedActionCount);
                    options = options.WithChangedOption(AnalyzerABTestOptions.UsedSuggestedActionCount, ++usageCount);

                    if (usageCount >= 3)
                    {
                        isCandidate = true;
                        options     = options.WithChangedOption(AnalyzerABTestOptions.HasMetCandidacyRequirements, true);
                        AnalyzerABTestLogger.Log(nameof(AnalyzerABTestOptions.HasMetCandidacyRequirements));
                    }

                    _workspace.Options = options;
                }
            }

            return(isCandidate);
        }
Example #3
0
            public async Task MergeAsync(ActiveFileState state, Document document)
            {
                Contract.ThrowIfFalse(state.DocumentId == document.Id);

                // merge active file state to project state
                var lastResult = _lastResult;

                var syntax   = state.GetAnalysisData(AnalysisKind.Syntax);
                var semantic = state.GetAnalysisData(AnalysisKind.Semantic);

                AnalyzerABTestLogger.LogDocumentDiagnostics(document, _owner.StateName, syntax.Items, semantic.Items);

                var project = document.Project;

                // if project didn't successfully loaded, then it is same as FSA off
                var fullAnalysis = ServiceFeatureOnOffOptions.IsClosedFileDiagnosticsEnabled(project) &&
                                   await project.HasSuccessfullyLoadedAsync(CancellationToken.None).ConfigureAwait(false);

                // keep from build flag if full analysis is off
                var fromBuild = fullAnalysis ? false : lastResult.FromBuild;

                var openFileOnlyAnalyzer = _owner.Analyzer.IsOpenFileOnly(document.Project.Solution.Workspace);

                // if it is allowed to keep project state, check versions and if they are same, bail out.
                // if full solution analysis is off or we are asked to reset document state, we always merge.
                if (fullAnalysis && !openFileOnlyAnalyzer &&
                    syntax.Version != VersionStamp.Default &&
                    syntax.Version == semantic.Version &&
                    syntax.Version == lastResult.Version)
                {
                    // all data is in sync already.
                    return;
                }

                // we have mixed versions or full analysis is off, set it to default so that it can be re-calculated next time so data can be in sync.
                var version = VersionStamp.Default;

                // serialization can't be cancelled.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, version);

                // save active file diagnostics back to project state
                await SerializeAsync(serializer, document, document.Id, _owner.SyntaxStateName, syntax.Items).ConfigureAwait(false);
                await SerializeAsync(serializer, document, document.Id, _owner.SemanticStateName, semantic.Items).ConfigureAwait(false);

                // save last aggregated form of analysis result
                _lastResult = _lastResult.UpdateAggregatedResult(version, state.DocumentId, fromBuild);
            }
Example #4
0
        private bool IsVsixInstalled()
        {
            if (_installStatus == LiveCodeAnalysisInstallStatus.Unknown)
            {
                var vsShell = _serviceProvider.GetService(typeof(SVsShell)) as IVsShell;
                var hr      = vsShell.IsPackageInstalled(FxCopAnalyzersPackageGuid, out int installed);
                if (ErrorHandler.Failed(hr))
                {
                    FatalError.ReportWithoutCrash(Marshal.GetExceptionForHR(hr));

                    // We set installed to ensure we don't go through this again next time a
                    // suggested action is called, and we don't want to continue if the shell
                    // is busted.
                    _installStatus = LiveCodeAnalysisInstallStatus.Installed;
                }
                else
                {
                    _installStatus = installed != 0 ? LiveCodeAnalysisInstallStatus.Installed : LiveCodeAnalysisInstallStatus.NotInstalled;
                    AnalyzerABTestLogger.LogInstallationStatus(_workspace, _installStatus);
                }
            }

            return(_installStatus == LiveCodeAnalysisInstallStatus.Installed);
        }
Example #5
0
            public async Task SaveAsync(Project project, DiagnosticAnalysisResult result)
            {
                Contract.ThrowIfTrue(result.IsAggregatedForm);

                RemoveInMemoryCache(_lastResult);

                // save last aggregated form of analysis result
                _lastResult = result.ToAggregatedForm();

                // serialization can't be cancelled.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, result.Version);

                foreach (var documentId in result.DocumentIds)
                {
                    var document = project.GetDocument(documentId);
                    if (document == null)
                    {
                        // it can happen with build synchronization since, in build case,
                        // we don't have actual snapshot (we have no idea what sources out of proc build has picked up)
                        // so we might be out of sync.
                        // example of such cases will be changing anything about solution while building is going on.
                        // it can be user explict actions such as unloading project, deleting a file, but also it can be
                        // something project system or roslyn workspace does such as populating workspace right after
                        // solution is loaded.
                        continue;
                    }

                    await SerializeAsync(serializer, document, document.Id, _owner.SyntaxStateName, GetResult(result, AnalysisKind.Syntax, document.Id)).ConfigureAwait(false);
                    await SerializeAsync(serializer, document, document.Id, _owner.SemanticStateName, GetResult(result, AnalysisKind.Semantic, document.Id)).ConfigureAwait(false);
                    await SerializeAsync(serializer, document, document.Id, _owner.NonLocalStateName, GetResult(result, AnalysisKind.NonLocal, document.Id)).ConfigureAwait(false);
                }

                await SerializeAsync(serializer, project, result.ProjectId, _owner.NonLocalStateName, result.Others).ConfigureAwait(false);

                AnalyzerABTestLogger.LogProjectDiagnostics(project, _owner.StateName, result);
            }
Example #6
0
 private void DoNotShowAgain()
 {
     _workspace.Options = _workspace.Options.WithChangedOption(AnalyzerABTestOptions.NeverShowAgain, true);
     AnalyzerABTestLogger.Log(nameof(AnalyzerABTestOptions.NeverShowAgain));
 }
Example #7
0
 private void OpenInstallHyperlink()
 {
     System.Diagnostics.Process.Start(AnalyzerVsixHyperlink);
     AnalyzerABTestLogger.Log(nameof(AnalyzerVsixHyperlink));
 }