// Called by us to update entries
        public override void UpdateFileInfo(ProjectSnapshot projectSnapshot, DocumentSnapshot document)
        {
            if (projectSnapshot == null)
            {
                throw new ArgumentNullException(nameof(projectSnapshot));
            }

            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            // There's a possible race condition here where we're processing an update
            // and the project is getting unloaded. So if we don't find an entry we can
            // just ignore it.
            var key = new Key(projectSnapshot.FilePath, document.FilePath);

            if (_entries.TryGetValue(key, out var entry))
            {
                lock (entry.Lock)
                {
                    entry.Current = entry.Current
                                    .WithTextLoader(new GeneratedDocumentTextLoader(document, entry.Current.FilePath));
                }

                Updated?.Invoke(entry.Current);
            }
        }
        public Task <RazorCodeDocument> GetGeneratedOutputInitializationTask(ProjectSnapshot project, DocumentSnapshot document)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (_task == null)
            {
                lock (_lock)
                {
                    if (_task == null)
                    {
                        _task = GetGeneratedOutputInitializationTaskCore(project, document);
                    }
                }
            }

            return(_task);
        }
Beispiel #3
0
 public DefaultImportDocumentSnapshot(ProjectSnapshot project, RazorProjectItem item)
 {
     _project         = project;
     _importItem      = item;
     _version         = VersionStamp.Default;
     _generatedOutput = new DocumentGeneratedOutputTracker(null);
 }
Beispiel #4
0
        public IReadOnlyList <DocumentSnapshot> GetImports(ProjectSnapshot project, DocumentSnapshot document)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (_imports == null)
            {
                lock (_lock)
                {
                    if (_imports == null)
                    {
                        _imports = GetImportsCore(project, document);
                    }
                }
            }

            return(_imports);
        }
        // Called by us when a document opens in the editor
        public override void SuppressDocument(ProjectSnapshot project, DocumentSnapshot document)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            // There's a possible race condition here where we're processing an update
            // and the project is getting unloaded. So if we don't find an entry we can
            // just ignore it.
            var key = new Key(project.FilePath, document.FilePath);

            if (_entries.TryGetValue(key, out var entry))
            {
                var updated = false;
                lock (entry.Lock)
                {
                    if (entry.Current.TextLoader is GeneratedDocumentTextLoader)
                    {
                        updated       = true;
                        entry.Current = entry.Current.WithTextLoader(new EmptyTextLoader(entry.Current.FilePath));
                    }
                }

                if (updated)
                {
                    Updated?.Invoke(entry.Current);
                }
            }
        }
        public DefaultRazorDocumentInfoProviderTest()
        {
            ProjectSnapshotManager = new TestProjectSnapshotManager(Workspace);

            var hostProject = new HostProject("C:/path/to/project.csproj", RazorConfiguration.Default, "RootNamespace");

            ProjectSnapshotManager.ProjectAdded(hostProject);

            var hostDocument   = new HostDocument("C:/path/to/document.cshtml", "/C:/path/to/document.cshtml");
            var sourceText     = SourceText.From("Hello World");
            var textAndVersion = TextAndVersion.Create(sourceText, VersionStamp.Default, hostDocument.FilePath);

            ProjectSnapshotManager.DocumentAdded(hostProject, hostDocument, TextLoader.From(textAndVersion));

            ProjectSnapshot  = ProjectSnapshotManager.Projects[0];
            DocumentSnapshot = ProjectSnapshot.GetDocument(hostDocument.FilePath);
            var factory = new Mock <VisualStudioMacDocumentInfoFactory>();

            factory.Setup(f => f.CreateEmpty(It.IsAny <string>(), It.IsAny <ProjectId>()))
            .Returns <string, ProjectId>((razorFilePath, projectId) =>
            {
                var documentId   = DocumentId.CreateNewId(projectId);
                var documentInfo = DocumentInfo.Create(documentId, "testDoc", filePath: razorFilePath);
                return(documentInfo);
            });
            Factory = factory.Object;
        }
        // Called by us to update entries
        public void UpdateFileInfo(ProjectSnapshot project, DocumentSnapshot document)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (project.WorkspaceProject == null)
            {
                // Don't bother if this isn't assocated with a project.
                return;
            }

            // There's a possible race condition here where we're processing an update
            // and the project is getting unloaded. So if we don't find an entry we can
            // just ignore it.
            var key = new Key(project.WorkspaceProject.Id, project.WorkspaceProject.FilePath, document.FilePath);

            if (_entries.TryGetValue(key, out var entry))
            {
                lock (entry.Lock)
                {
                    entry.Current = CreateInfo(key, document);
                }

                Updated?.Invoke(this, document.FilePath);
            }
        }
        public RazorDocumentInfoProviderTest()
        {
            var serviceProviderFactory          = new DefaultRazorDocumentServiceProviderFactory();
            var lspEditorEnabledFeatureDetector = Mock.Of <LSPEditorFeatureDetector>(detector => detector.IsLSPEditorFeatureEnabled() == true, MockBehavior.Strict);

            InnerDynamicDocumentInfoProvider = new DefaultRazorDynamicFileInfoProvider(serviceProviderFactory, lspEditorEnabledFeatureDetector);
            ProjectSnapshotManager           = new TestProjectSnapshotManager(Workspace);

            var hostProject = new HostProject("C:/path/to/project.csproj", RazorConfiguration.Default, "RootNamespace");

            ProjectSnapshotManager.ProjectAdded(hostProject);

            var hostDocument   = new HostDocument("C:/path/to/document.cshtml", "/C:/path/to/document.cshtml");
            var sourceText     = SourceText.From("Hello World");
            var textAndVersion = TextAndVersion.Create(sourceText, VersionStamp.Default, hostDocument.FilePath);

            ProjectSnapshotManager.DocumentAdded(hostProject, hostDocument, TextLoader.From(textAndVersion));

            ProjectSnapshot  = ProjectSnapshotManager.Projects[0];
            DocumentSnapshot = ProjectSnapshot.GetDocument(hostDocument.FilePath);
            var factory = new Mock <VisualStudioMacDocumentInfoFactory>(MockBehavior.Strict);

            factory.Setup(f => f.CreateEmpty(It.IsAny <string>(), It.IsAny <ProjectId>()))
            .Returns <string, ProjectId>((razorFilePath, projectId) =>
            {
                var documentId   = DocumentId.CreateNewId(projectId);
                var documentInfo = DocumentInfo.Create(documentId, "testDoc", filePath: razorFilePath);
                return(documentInfo);
            });
            Factory = factory.Object;
        }
Beispiel #9
0
        public override void ReportError(Exception exception, ProjectSnapshot project)
        {
            if (exception == null)
            {
                throw new ArgumentNullException(nameof(exception));
            }

            _errorReporter.ReportError(exception, project);
        }
        public bool HaveTagHelpersChanged(ProjectSnapshot original)
        {
            if (original == null)
            {
                throw new ArgumentNullException(nameof(original));
            }

            return(!Enumerable.SequenceEqual(TagHelpers, original.TagHelpers));
        }
        public bool HasChangesComparedTo(ProjectSnapshot original)
        {
            if (original == null)
            {
                throw new ArgumentNullException(nameof(original));
            }

            return(!object.Equals(Configuration, original.Configuration));
        }
Beispiel #12
0
        /// <summary>
        /// Gets the version of this project based on the computed state, NOT INCLUDING content
        /// changes. The computed state is guaranteed to change when the configuration or tag helpers
        /// change.
        /// </summary>
        /// <returns>Asynchronously returns the computed version.</returns>
        public async Task <VersionStamp> GetComputedStateVersionAsync(ProjectSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            var(_, version) = await ComputedState.GetTagHelpersAndVersionAsync(snapshot).ConfigureAwait(false);

            return(version);
        }
Beispiel #13
0
        public async Task <IReadOnlyList <TagHelperDescriptor> > GetTagHelpersAsync(ProjectSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            var(tagHelpers, _) = await ComputedState.GetTagHelpersAndVersionAsync(snapshot).ConfigureAwait(false);

            return(tagHelpers);
        }
        private bool TryGetProjectSnapshot(string projectFilePath, out ProjectSnapshot projectSnapshot)
        {
            if (projectFilePath == null)
            {
                projectSnapshot = null;
                return(false);
            }

            projectSnapshot = _projectManager.GetLoadedProject(projectFilePath);
            return(projectSnapshot != null);
        }
        public ProjectChangeEventArgs(ProjectSnapshot older, ProjectSnapshot newer, ProjectChangeKind kind)
        {
            if (older == null && newer == null)
            {
                throw new ArgumentException("Both projects cannot be null.");
            }

            Older = older;
            Newer = newer;
            Kind  = kind;

            ProjectFilePath = older?.FilePath ?? newer.FilePath;
        }
        private async Task <IReadOnlyList <ImportItem> > GetImportsAsync(ProjectSnapshot project, DocumentSnapshot document)
        {
            var imports = new List <ImportItem>();

            foreach (var snapshot in document.GetImports())
            {
                var versionStamp = await snapshot.GetTextVersionAsync();

                imports.Add(new ImportItem(snapshot.FilePath, versionStamp, snapshot));
            }

            return(imports);
        }
Beispiel #17
0
        public ProjectChangeEventArgs(ProjectSnapshot older, ProjectSnapshot newer, string documentFilePath, ProjectChangeKind kind, bool solutionIsClosing)
        {
            if (older == null && newer == null)
            {
                throw new ArgumentException("Both projects cannot be null.");
            }

            Older             = older;
            Newer             = newer;
            DocumentFilePath  = documentFilePath;
            Kind              = kind;
            SolutionIsClosing = solutionIsClosing;
            ProjectFilePath   = older?.FilePath ?? newer.FilePath;
        }
        public DefaultDocumentSnapshot(ProjectSnapshot project, DocumentState state)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            Project = project;
            State   = state;
        }
Beispiel #19
0
        public RazorProjectEngine GetProjectEngine(ProjectSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            if (_projectEngine == null)
            {
                lock (_lock)
                {
                    if (_projectEngine == null)
                    {
                        var factory = _services.GetRequiredService <ProjectSnapshotProjectEngineFactory>();
                        _projectEngine = factory.Create(snapshot);
                    }
                }
            }

            return(_projectEngine);
        }
Beispiel #20
0
        private IReadOnlyList <DocumentSnapshot> GetImportsCore(ProjectSnapshot project, DocumentSnapshot document)
        {
            var projectEngine = project.GetProjectEngine();
            var importFeature = projectEngine.ProjectFeatures.OfType <IImportProjectFeature>().FirstOrDefault();
            var projectItem   = projectEngine.FileSystem.GetItem(document.FilePath);
            var importItems   = importFeature?.GetImports(projectItem).Where(i => i.Exists);

            if (importItems == null)
            {
                return(Array.Empty <DocumentSnapshot>());
            }

            var imports = new List <DocumentSnapshot>();

            foreach (var item in importItems)
            {
                if (item.PhysicalPath == null)
                {
                    // This is a default import.
                    var defaultImport = new DefaultImportDocumentSnapshot(project, item);
                    imports.Add(defaultImport);
                }
                else
                {
                    var import = project.GetDocument(item.PhysicalPath);
                    if (import == null)
                    {
                        // We are not tracking this document in this project. So do nothing.
                        continue;
                    }

                    imports.Add(import);
                }
            }

            return(imports);
        }
 public override RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action <RazorProjectEngineBuilder> configure)
 {
     return(Engine ?? RazorProjectEngine.Create(project.Configuration, fileSystem, configure));
 }
Beispiel #22
0
 public abstract void ReportError(Exception exception, ProjectSnapshot project);
Beispiel #23
0
 public ProjectChangeEventArgs(ProjectSnapshot older, ProjectSnapshot newer, ProjectChangeKind kind)
     : this(older, newer, null, kind, false)
 {
 }
Beispiel #24
0
 public static ProjectChangeEventArgs CreateTestInstance(ProjectSnapshot older, ProjectSnapshot newer, string documentFilePath, ProjectChangeKind kind, bool solutionIsClosing = false) =>
Beispiel #25
0
        private async Task <RazorCodeDocument> GetGeneratedOutputInitializationTaskCore(ProjectSnapshot project, DocumentSnapshot document)
        {
            var tagHelpers = await project.GetTagHelpersAsync().ConfigureAwait(false);

            if (_older != null && _older.IsResultAvailable)
            {
                var difference = new HashSet <TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
                difference.UnionWith(_older._tagHelpers);
                difference.SymmetricExceptWith(tagHelpers);

                if (difference.Count == 0)
                {
                    // We can use the cached result.
                    var result = _older._task.Result;

                    // Drop reference so it can be GC'ed
                    _older = null;

                    // Cache the tag helpers so the next version can use them
                    _tagHelpers = tagHelpers;

                    return(result);
                }
            }

            // Drop reference so it can be GC'ed
            _older = null;


            // Cache the tag helpers so the next version can use them
            _tagHelpers = tagHelpers;

            var projectEngine = project.GetProjectEngine();
            var projectItem   = projectEngine.FileSystem.GetItem(document.FilePath);

            return(projectItem == null ? null : projectEngine.ProcessDesignTime(projectItem));
        }
Beispiel #26
0
            private async Task <(IReadOnlyList <TagHelperDescriptor>, VersionStamp)> GetTagHelpersAndVersionCoreAsync(ProjectSnapshot snapshot)
            {
                // Don't allow synchronous execution - we expect this to always be called with the lock.
                await Task.Yield();

                var services = ((DefaultProjectSnapshot)snapshot).State.Services;
                var resolver = services.GetLanguageServices(RazorLanguage.Name).GetRequiredService <TagHelperResolver>();

                var tagHelpers = (await resolver.GetTagHelpersAsync(snapshot).ConfigureAwait(false)).Descriptors;

                if (_older?.TaskUnsafe != null)
                {
                    // We have something to diff against.
                    var(olderTagHelpers, olderVersion) = await _older.TaskUnsafe.ConfigureAwait(false);

                    var difference = new HashSet <TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
                    difference.UnionWith(olderTagHelpers);
                    difference.SymmetricExceptWith(tagHelpers);

                    if (difference.Count == 0)
                    {
                        lock (_lock)
                        {
                            // Everything is the same. Return the cached version.
                            TaskUnsafe = _older.TaskUnsafe;
                            _older     = null;
                            return(olderTagHelpers, olderVersion);
                        }
                    }
                }

                lock (_lock)
                {
                    _older = null;
                    return(tagHelpers, _projectStateVersion);
                }
            }
Beispiel #27
0
            public Task <(IReadOnlyList <TagHelperDescriptor>, VersionStamp)> GetTagHelpersAndVersionAsync(ProjectSnapshot snapshot)
            {
                if (TaskUnsafe == null)
                {
                    lock (_lock)
                    {
                        if (TaskUnsafe == null)
                        {
                            TaskUnsafe = GetTagHelpersAndVersionCoreAsync(snapshot);
                        }
                    }
                }

                return(TaskUnsafe);
            }
 public override IProjectEngineFactory FindSerializableFactory(ProjectSnapshot project)
 {
     throw new NotImplementedException();
 }
        private async Task <RazorCodeDocument> GetGeneratedOutputInitializationTaskCore(ProjectSnapshot project, DocumentSnapshot document)
        {
            var tagHelpers = await project.GetTagHelpersAsync().ConfigureAwait(false);

            var imports = await GetImportsAsync(project, document);

            if (_older != null && _older.IsResultAvailable)
            {
                var tagHelperDifference = new HashSet <TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
                tagHelperDifference.UnionWith(_older._tagHelpers);
                tagHelperDifference.SymmetricExceptWith(tagHelpers);

                var importDifference = new HashSet <ImportItem>();
                importDifference.UnionWith(_older._imports);
                importDifference.SymmetricExceptWith(imports);

                if (tagHelperDifference.Count == 0 && importDifference.Count == 0)
                {
                    // We can use the cached result.
                    var result = _older._task.Result;

                    // Drop reference so it can be GC'ed
                    _older = null;

                    // Cache the tag helpers and imports so the next version can use them
                    _tagHelpers = tagHelpers;
                    _imports    = imports;

                    return(result);
                }
            }

            // Drop reference so it can be GC'ed
            _older = null;

            // Cache the tag helpers and imports so the next version can use them
            _tagHelpers = tagHelpers;
            _imports    = imports;

            var importSources = new List <RazorSourceDocument>();

            foreach (var item in imports)
            {
                var sourceDocument = await GetRazorSourceDocumentAsync(item.Import);

                importSources.Add(sourceDocument);
            }

            var documentSource = await GetRazorSourceDocumentAsync(document);

            var projectEngine = project.GetProjectEngine();

            return(projectEngine.ProcessDesignTime(documentSource, importSources, tagHelpers));
        }
 public DefaultImportDocumentSnapshot(ProjectSnapshot project, RazorProjectItem item)
 {
     _project    = project;
     _importItem = item;
     _version    = VersionStamp.Default;
 }