Example #1
0
        public void VsTextViewCreated(IVsTextView textViewAdapter)
        {
            IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter);

            if (!DocumentService.TryGetTextDocument(textView.TextBuffer, out ITextDocument doc))
            {
                return;
            }

            string fileName = Path.GetFileName(doc.FilePath);

            if (!fileName.Equals(Constants.ConfigFileName, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            new CompletionController(textViewAdapter, textView, CompletionBroker);

            _dependencies = Dependencies.FromConfigFile(doc.FilePath);
            _manifest     = Manifest.FromFileAsync(doc.FilePath, _dependencies, CancellationToken.None).Result;
            _manifestPath = doc.FilePath;
            _project      = VsHelpers.GetDTEProjectFromConfig(_manifestPath);

            doc.FileActionOccurred += OnFileSaved;
            textView.Closed        += OnViewClosed;

            Task.Run(async() =>
            {
                IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(_manifest, _dependencies, CancellationToken.None).ConfigureAwait(false);
                if (!results.All(r => r.Success))
                {
                    AddErrorsToList(results);
                }
            });
        }
        public async Task DetectConflictsAsync_ConflictingFiles_DifferentDestinations()
        {
            var manifest = Manifest.FromJson(_docDifferentLibraries_SameFiles_DifferentLocation, _dependencies);

            IEnumerable <ILibraryOperationResult> conflicts = await LibrariesValidator.GetManifestErrorsAsync(manifest, _dependencies, CancellationToken.None);

            Assert.IsTrue(conflicts.All(c => c.Success));
        }
        public async Task GetLibrariesErrors_LibrariesNoProvider()
        {
            string expectedErrorCode = "LIB007";
            var    manifest          = Manifest.FromJson(_docNoProvider, _dependencies);

            IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(manifest, _dependencies, CancellationToken.None);

            var resultsList = results.ToList();

            Assert.AreEqual(1, resultsList.Count);
            Assert.IsTrue(resultsList[0].Errors.Count == 1);
            Assert.AreEqual(resultsList[0].Errors[0].Code, expectedErrorCode);
        }
        public async Task GetManifestErrors_ManifestIsNull()
        {
            string   expectedErrorCode = "LIB004";
            Manifest manifest          = null;

            IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(manifest, _dependencies, CancellationToken.None);

            var resultsList = results.ToList();

            Assert.AreEqual(1, resultsList.Count);
            Assert.IsTrue(resultsList[0].Errors.Count == 1);
            Assert.AreEqual(resultsList[0].Errors[0].Code, expectedErrorCode);
        }
        private async Task RestoreInternalAsync(IDictionary <string, Manifest> manifests, CancellationToken cancellationToken)
        {
            Logger.LogEventsHeader(OperationType.Restore, string.Empty);

            try
            {
                Stopwatch swTotal = new Stopwatch();
                swTotal.Start();

                foreach (KeyValuePair <string, Manifest> manifest in manifests)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Stopwatch swLocal = new Stopwatch();
                    swLocal.Start();
                    IDependencies dependencies = _dependenciesFactory.FromConfigFile(manifest.Key);
                    Project       project      = VsHelpers.GetDTEProjectFromConfig(manifest.Key);

                    Logger.LogEvent(string.Format(LibraryManager.Resources.Text.Restore_LibrariesForProject, project?.Name), LogLevel.Operation);

                    IEnumerable <ILibraryOperationResult> validationResults = await LibrariesValidator.GetManifestErrorsAsync(manifest.Value, dependencies, cancellationToken).ConfigureAwait(false);

                    if (!validationResults.All(r => r.Success))
                    {
                        swLocal.Stop();
                        AddErrorsToErrorList(project?.Name, manifest.Key, validationResults);
                        Logger.LogErrorsSummary(validationResults, OperationType.Restore, false);
                        Telemetry.LogErrors($"FailValidation_{OperationType.Restore}", validationResults);
                    }
                    else
                    {
                        IEnumerable <ILibraryOperationResult> results = await RestoreLibrariesAsync(manifest.Value, cancellationToken).ConfigureAwait(false);
                        await AddFilesToProjectAsync(manifest.Key, project, results.Where(r => r.Success && !r.UpToDate), cancellationToken).ConfigureAwait(false);

                        swLocal.Stop();
                        AddErrorsToErrorList(project?.Name, manifest.Key, results);
                        Logger.LogEventsSummary(results, OperationType.Restore, swLocal.Elapsed, false);
                        Telemetry.LogEventsSummary(results, OperationType.Restore, swLocal.Elapsed);
                    }
                }

                swTotal.Stop();
                Logger.LogEventsFooter(OperationType.Restore, swTotal.Elapsed);
            }
            catch (OperationCanceledException ex)
            {
                Logger.LogEvent(LibraryManager.Resources.Text.Restore_OperationCancelled, LogLevel.Task);
                Telemetry.TrackException($@"{OperationType.Restore}Cancelled", ex);
            }
        }
        public async Task DetectConflictsAsync_SameLibrary_DifferentVersions_DifferentFiles()
        {
            string expectedErrorCode    = "LIB019";
            string expectedErrorMessage = "Cannot restore. Multiple definitions for libraries: jquery";
            var    manifest             = Manifest.FromJson(_docSameLibrary_DifferentVersions_DifferentFiles, _dependencies);

            IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(manifest, _dependencies, CancellationToken.None);

            var conflictsList = results.ToList();

            Assert.AreEqual(1, conflictsList.Count);
            Assert.IsTrue(conflictsList[0].Errors.Count == 1);
            Assert.AreEqual(conflictsList[0].Errors[0].Code, expectedErrorCode);
            Assert.AreEqual(conflictsList[0].Errors[0].Message, expectedErrorMessage);
        }
        public async Task DetectConflictsAsync_ConflictingFiles_SameDestination()
        {
            string expectedErrorCode    = "LIB016";
            string expectedErrorMessage = "Conflicting file \"lib\\package.json\" found in more than one library: [email protected], [email protected]";
            var    manifest             = Manifest.FromJson(_docDifferentLibraries_SameFiles_SameLocation, _dependencies);

            IEnumerable <ILibraryOperationResult> conflicts = await LibrariesValidator.GetManifestErrorsAsync(manifest, _dependencies, CancellationToken.None);

            var conflictsList = conflicts.ToList();

            Assert.AreEqual(1, conflictsList.Count);
            Assert.IsTrue(conflictsList[0].Errors.Count == 1);
            Assert.AreEqual(conflictsList[0].Errors[0].Code, expectedErrorCode);
            Assert.AreEqual(conflictsList[0].Errors[0].Message, expectedErrorMessage);
        }
        private async Task CleanLibrariesAsync(ProjectItem configProjectItem, CancellationToken cancellationToken)
        {
            Logger.LogEventsHeader(OperationType.Clean, string.Empty);

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();

                string  configFileName = configProjectItem.FileNames[1];
                var     dependencies   = _dependenciesFactory.FromConfigFile(configFileName);
                Project project        = VsHelpers.GetDTEProjectFromConfig(configFileName);

                Manifest manifest = await Manifest.FromFileAsync(configFileName, dependencies, CancellationToken.None).ConfigureAwait(false);

                IEnumerable <ILibraryOperationResult> results = new List <ILibraryOperationResult>();

                if (manifest != null)
                {
                    IEnumerable <ILibraryOperationResult> validationResults = await LibrariesValidator.GetManifestErrorsAsync(manifest, dependencies, cancellationToken).ConfigureAwait(false);

                    if (!validationResults.All(r => r.Success))
                    {
                        sw.Stop();
                        AddErrorsToErrorList(project?.Name, configFileName, validationResults);
                        Logger.LogErrorsSummary(validationResults, OperationType.Clean);
                        Telemetry.LogErrors($"FailValidation_{OperationType.Clean}", validationResults);
                    }
                    else
                    {
                        IHostInteraction hostInteraction = dependencies.GetHostInteractions();
                        results = await manifest.CleanAsync(async (filesPaths) => await hostInteraction.DeleteFilesAsync(filesPaths, cancellationToken), cancellationToken);

                        sw.Stop();
                        AddErrorsToErrorList(project?.Name, configFileName, results);
                        Logger.LogEventsSummary(results, OperationType.Clean, sw.Elapsed);
                        Telemetry.LogEventsSummary(results, OperationType.Clean, sw.Elapsed);
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                Logger.LogEvent(LibraryManager.Resources.Text.Clean_OperationCancelled, LogLevel.Task);
                Telemetry.TrackException($@"{OperationType.Clean}Cancelled", ex);
            }
        }
        public void VsTextViewCreated(IVsTextView textViewAdapter)
        {
            IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter);

            if (!DocumentService.TryGetTextDocument(textView.TextBuffer, out ITextDocument doc))
            {
                return;
            }

            string fileName = Path.GetFileName(doc.FilePath);

            if (!fileName.Equals(Constants.ConfigFileName, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            new CompletionController(textViewAdapter, textView, CompletionBroker);

            IDependencies dependencies = DependenciesFactory.FromConfigFile(doc.FilePath);

#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
                                  // Justification: Manifest is free-threaded, don't need to use JTF here
            _manifest = Manifest.FromFileAsync(doc.FilePath, dependencies, CancellationToken.None).Result;
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
            _manifestPath = doc.FilePath;
            _project      = VsHelpers.GetDTEProjectFromConfig(_manifestPath);

            doc.FileActionOccurred += OnFileSaved;
            textView.Closed        += OnViewClosed;

            _ = Task.Run(async() =>
            {
                IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(_manifest, dependencies, CancellationToken.None).ConfigureAwait(false);
                if (!results.All(r => r.Success))
                {
                    AddErrorsToList(results);
                    Telemetry.LogErrors("Fail-ManifestFileOpenWithErrors", results);
                }
            });
        }
        private void OnFileSaved(object sender, TextDocumentFileActionEventArgs e)
        {
            if (LibraryCommandService.IsOperationInProgress)
            {
                Logger.LogEvent(Resources.Text.OperationInProgress, LogLevel.Operation);
            }

            var textDocument = sender as ITextDocument;

            if (e.FileActionType == FileActionTypes.ContentSavedToDisk && textDocument != null)
            {
                _ = Task.Run(async() =>
                {
                    try
                    {
                        var newManifest = Manifest.FromJson(textDocument.TextBuffer.CurrentSnapshot.GetText(), _dependencies);
                        IEnumerable <ILibraryOperationResult> results = await LibrariesValidator.GetManifestErrorsAsync(newManifest, _dependencies, CancellationToken.None).ConfigureAwait(false);

                        if (!results.All(r => r.Success))
                        {
                            AddErrorsToList(results);
                            Logger.LogErrorsSummary(results, OperationType.Restore);
                            Telemetry.LogErrors("Fail-ManifestFileSaveWithErrors", results);
                        }
                        else
                        {
                            if (_manifest == null || await _manifest.RemoveUnwantedFilesAsync(newManifest, CancellationToken.None).ConfigureAwait(false))
                            {
                                _manifest = newManifest;

                                await LibraryCommandService.RestoreAsync(textDocument.FilePath, _manifest, CancellationToken.None).ConfigureAwait(false);
                                Telemetry.TrackUserTask("Invoke-RestoreOnSave");
                            }
                            else
                            {
                                string textMessage = string.Concat(Environment.NewLine, LibraryManager.Resources.Text.Restore_OperationHasErrors, Environment.NewLine);
                                Logger.LogErrorsSummary(new[] { textMessage }, OperationType.Restore);
                                Telemetry.TrackUserTask("Fail-RemovedUnwantedFiles", TelemetryResult.Failure);
                            }
                        }
                    }
                    catch (OperationCanceledException ex)
                    {
                        string textMessage = string.Concat(Environment.NewLine, LibraryManager.Resources.Text.Restore_OperationCancelled, Environment.NewLine);

                        Logger.LogEvent(textMessage, LogLevel.Task);
                        Logger.LogEvent(ex.ToString(), LogLevel.Error);

                        Telemetry.TrackException("RestoreOnSaveCancelled", ex);
                    }
                    catch (Exception ex)
                    {
                        // TO DO: Restore to previous state
                        // and add a warning to the Error List

                        string textMessage = string.Concat(Environment.NewLine, LibraryManager.Resources.Text.Restore_OperationHasErrors, Environment.NewLine);

                        Logger.LogEvent(textMessage, LogLevel.Task);
                        Logger.LogEvent(ex.ToString(), LogLevel.Error);
                        Telemetry.TrackException("RestoreOnSaveFailed", ex);
                    }
                });
            }
        }