// 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); }
public DefaultImportDocumentSnapshot(ProjectSnapshot project, RazorProjectItem item) { _project = project; _importItem = item; _version = VersionStamp.Default; _generatedOutput = new DocumentGeneratedOutputTracker(null); }
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; }
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)); }
/// <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); }
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); }
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; }
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); }
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)); }
public abstract void ReportError(Exception exception, ProjectSnapshot project);
public ProjectChangeEventArgs(ProjectSnapshot older, ProjectSnapshot newer, ProjectChangeKind kind) : this(older, newer, null, kind, false) { }
public static ProjectChangeEventArgs CreateTestInstance(ProjectSnapshot older, ProjectSnapshot newer, string documentFilePath, ProjectChangeKind kind, bool solutionIsClosing = false) =>
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)); }
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); } }
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; }