public override EnvDTE.FileCodeModel GetFileCodeModel(DocumentId documentId) { if (documentId == null) { throw new ArgumentNullException(nameof(documentId)); } var project = CurrentSolution.GetProject(documentId.ProjectId); if (project == null) { throw new ArgumentException(ServicesVSResources.The_given_DocumentId_did_not_come_from_the_Visual_Studio_workspace, nameof(documentId)); } var documentFilePath = GetFilePath(documentId); if (documentFilePath == null) { throw new ArgumentException(ServicesVSResources.The_given_DocumentId_did_not_come_from_the_Visual_Studio_workspace, nameof(documentId)); } IProjectCodeModel projectCodeModel = _projectCodeModelFactory.Value.GetProjectCodeModel(project.Id); return(projectCodeModel.GetOrCreateFileCodeModel(documentFilePath)); }
public Project AddProject(string name, string language) { ProjectInfo projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(null), VersionStamp.Create(), name, name, language); OnProjectAdded(projectInfo); return(CurrentSolution.GetProject(projectInfo.Id)); }
public override Compilation GetCompilation(string assemblyName) { var project = CurrentSolution.GetProject(ProjectId); var parseOptions = CreateParseOptions(); var trees = project.Documents.Select(document => SyntaxFactory.ParseSyntaxTree(document.GetTextAsync().Result, parseOptions, string.Empty)); var compilationOptions = new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, mainTypeName: null, scriptClassName: null, usings: ImmutableArray <string> .Empty, optimizationLevel: OptimizationLevel.Debug, // TODO checkOverflow: false, // TODO allowUnsafe: true, // TODO platform: Platform.AnyCpu, warningLevel: 4, xmlReferenceResolver: null, sourceReferenceResolver: null, metadataReferenceResolver: null, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default ); //.WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes), var compilation = CSharpCompilation.Create( assemblyName, // Assembly name trees, AllReferences, compilationOptions); return(compilation); }
public void TryPromoteMiscellaneousDocumentsToProject(Project project) { if (project == null) { throw new ArgumentNullException(nameof(project)); } var miscProjectInfos = miscDocumentsProjectInfos.Values.ToArray(); for (var i = 0; i < miscProjectInfos.Length; i++) { var miscProject = CurrentSolution.GetProject(miscProjectInfos[i].Id); var documents = miscProject.Documents.ToArray(); for (var j = 0; j < documents.Length; j++) { var document = documents[j]; if (FileBelongsToProject(document.FilePath, project)) { var textLoader = new DelegatingTextLoader(document); var documentId = DocumentId.CreateNewId(project.Id); var documentInfo = DocumentInfo.Create( documentId, document.FilePath, filePath: document.FilePath, loader: textLoader); // This transitively will remove the document from the misc project. AddDocument(documentInfo); } } } }
public Task <IReadOnlyList <Diagnostic> > GetDiagnosticsAsync(DocumentId documentId, CancellationToken cancellationToken) { return(Task.Run(async() => { var project = CurrentSolution.GetProject(documentId.ProjectId); var compilation = await project.GetCompilationAsync(cancellationToken); return (IReadOnlyList <Diagnostic>)compilation.GetDiagnostics(cancellationToken); }, cancellationToken)); }
public Document GetDocument(DocumentId documentId, CancellationToken cancellationToken = default(CancellationToken)) { var project = CurrentSolution.GetProject(documentId.ProjectId); if (project == null) { return(null); } return(project.GetDocument(documentId)); }
/// <summary> /// Finds the <see cref="DocumentId"/> related to the given <see cref="DocumentId"/> that /// is in the current context. For regular files (non-shared and non-linked) and closed /// linked files, this is always the provided <see cref="DocumentId"/>. For open linked /// files and open shared files, the active context is already tracked by the /// <see cref="Workspace"/> and can be looked up directly. For closed shared files, the /// document in the shared project's <see cref="__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy"/> /// is preferred. /// </summary> internal override DocumentId GetDocumentIdInCurrentContext(DocumentId documentId) { // If the document is open, then the Workspace knows the current context for both // linked and shared files if (IsDocumentOpen(documentId)) { return(base.GetDocumentIdInCurrentContext(documentId)); } var hostDocument = GetHostDocument(documentId); if (hostDocument == null) { // This can happen if the document was temporary and has since been closed/deleted. return(base.GetDocumentIdInCurrentContext(documentId)); } var itemId = hostDocument.GetItemId(); if (itemId == (uint)VSConstants.VSITEMID.Nil) { // An itemid is required to determine whether the file belongs to a Shared Project return(base.GetDocumentIdInCurrentContext(documentId)); } // If this is a regular document or a closed linked (non-shared) document, then use the // default logic for determining current context. var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hostDocument.Project.Hierarchy, itemId); if (sharedHierarchy == null) { return(base.GetDocumentIdInCurrentContext(documentId)); } // This is a closed shared document, so we must determine the correct context. var hostProject = LinkedFileUtilities.GetContextHostProject(sharedHierarchy, DeferredState.ProjectTracker); var matchingProject = CurrentSolution.GetProject(hostProject.Id); if (matchingProject == null || hostProject.Hierarchy == sharedHierarchy) { return(base.GetDocumentIdInCurrentContext(documentId)); } if (matchingProject.ContainsDocument(documentId)) { // The provided documentId is in the current context project return(documentId); } // The current context document is from another project. var linkedDocumentIds = CurrentSolution.GetDocument(documentId).GetLinkedDocumentIds(); var matchingDocumentId = linkedDocumentIds.FirstOrDefault(id => id.ProjectId == matchingProject.Id); return(matchingDocumentId ?? base.GetDocumentIdInCurrentContext(documentId)); }
public Project AddProject(ProjectInfo projectInfo) { if (projectInfo == null) { throw new ArgumentNullException(nameof(projectInfo)); } OnProjectAdded(projectInfo); UpdateReferencesAfterAdd(); return(CurrentSolution.GetProject(projectInfo.Id)); }
public async Task <(Project project, List <string> projectReferences, string targetPath)> AddProject(string solutionDir, string projectFile) { if (buildHost == null) { buildHost = new MSBuildHost(sdkPath); } var(info, projectReferences, targetPath) = await buildHost.LoadProject(solutionDir, projectFile); OnProjectAdded(info); return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath); }
public void RemoveMetadataReferences(ProjectId projectId) { if (projectId == null) { throw new ArgumentNullException(nameof(projectId)); } var project = CurrentSolution.GetProject(projectId); foreach (var metadataReference in project.MetadataReferences.ToImmutableArray()) { OnMetadataReferenceRemoved(projectId, metadataReference); } }
public async Task <ImmutableArray <SymbolRenameResult> > AnalyzeSolutionAsync( Func <Project, bool> predicate, CancellationToken cancellationToken = default) { ImmutableArray <ProjectId> projects = CurrentSolution .GetProjectDependencyGraph() .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); var results = new List <ImmutableArray <SymbolRenameResult> >(); Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; List <RenameScope> renameScopes = GetRenameScopes(); for (int i = 0; i < renameScopes.Count; i++) { WriteLine($"Rename {GetPluralName(renameScopes[i])} {$"{i + 1}/{renameScopes.Count}"}", Verbosity.Minimal); for (int j = 0; j < projects.Length; j++) { cancellationToken.ThrowIfCancellationRequested(); Project project = CurrentSolution.GetProject(projects[j]); if (predicate == null || predicate(project)) { WriteLine($" Rename {GetPluralName(renameScopes[i])} in '{project.Name}' {$"{j + 1}/{projects.Length}"}", ConsoleColors.Cyan, Verbosity.Minimal); ImmutableArray <SymbolRenameResult> projectResults = await AnalyzeProjectAsync(project, renameScopes[i], cancellationToken).ConfigureAwait(false); results.Add(projectResults); WriteLine($" Done renaming {GetPluralName(renameScopes[i])} in '{project.Name}' in {stopwatch.Elapsed - lastElapsed:mm\\:ss\\.ff}", Verbosity.Normal); } else { WriteLine($" Skip '{project.Name}' {$"{j + 1}/{projects.Length}"}", ConsoleColors.DarkGray, Verbosity.Minimal); } lastElapsed = stopwatch.Elapsed; } } stopwatch.Stop(); WriteLine($"Done renaming symbols in solution '{CurrentSolution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); return(results.SelectMany(f => f).ToImmutableArray()); }
public Task <BuildResult> BuildAsync(DocumentId documentId, CancellationToken cancellationToken) { return(Task.Run(async() => { var project = CurrentSolution.GetProject(documentId.ProjectId); var compilation = await project !.GetCompilationAsync(cancellationToken); using var peStream = new MemoryStream(); using var pdbStream = new MemoryStream(); var result = compilation !.Emit(peStream, pdbStream); var inMemoryAssembly = result.Success ? peStream.ToArray() : null; var inMemorySymbolStore = result.Success ? pdbStream.ToArray() : null; return new BuildResult(result.Diagnostics, inMemoryAssembly, inMemorySymbolStore); }, cancellationToken)); }
public void AddImports(ProjectId projectId, ImmutableArray <string> imports) { if (projectId == null) { throw new ArgumentNullException(nameof(projectId)); } var project = CurrentSolution.GetProject(projectId); var compilationOptions = (CSharpCompilationOptions)project.CompilationOptions; SetCurrentSolution( CurrentSolution.WithProjectCompilationOptions( projectId, compilationOptions.WithUsings(imports))); }
public virtual Document CreateAndOpenDocument(SourceTextContainer textContainer, Action <SourceText> onTextUpdated) { var project = CurrentSolution.GetProject(ProjectId); var documentId = DocumentId.CreateNewId(ProjectId); var newSolution = project.Solution.AddDocument(documentId, project.Name, textContainer.CurrentText); SetCurrentSolution(newSolution); OpenDocument(documentId, textContainer); if (null != onTextUpdated) { _sourceTextChangedHandlers[documentId] = onTextUpdated; } return(newSolution.GetDocument(documentId)); }
private void ResolveChildReferences(ProjectId project, ProjectId reference) { var refer = CurrentSolution.GetProject(reference); foreach (var child in refer.AllProjectReferences) { var proj = CurrentSolution.GetProject(project); if (!proj.AllProjectReferences.Contains(child)) { OnProjectReferenceAdded(project, child); } ResolveChildReferences(project, child.ProjectId); } }
protected override void ApplyDocumentAdded(DocumentInfo info, SourceText text) { var id = info.Id; MonoDevelop.Projects.Project mdProject = null; if (id.ProjectId != null) { var project = CurrentSolution.GetProject(id.ProjectId); mdProject = GetMonoProject(project); if (mdProject == null) { LoggingService.LogWarning("Couldn't find project for newly generated file {0} (Project {1}).", info.Name, info.Id.ProjectId); } } var path = DetermineFilePath(info.Id, info.Name, info.FilePath, info.Folders, mdProject?.FileName.ParentDirectory, true); string formattedText; var formatter = CodeFormatterService.GetFormatter(DesktopService.GetMimeTypeForUri(path)); if (formatter != null && mdProject != null) { formattedText = formatter.FormatText(mdProject.Policies, text.ToString()); } else { formattedText = text.ToString(); } var textSource = new StringTextSource(formattedText, text.Encoding ?? System.Text.Encoding.UTF8); try { textSource.WriteTextTo(path); } catch (Exception e) { LoggingService.LogError("Exception while saving file to " + path, e); } if (mdProject != null) { var file = new MonoDevelop.Projects.ProjectFile(path); Application.Invoke(delegate { mdProject.Files.Add(file); IdeApp.ProjectOperations.SaveAsync(mdProject); }); } }
public async Task <(Project project, List <string> projectReferences, string targetPath)> AddProject(string solutionDir, string projectFile) { var buildHost = _buildNodes.Take(); var(info, projectReferences, targetPath) = await buildHost.LoadProject(solutionDir, projectFile); _buildNodes.Add(buildHost); if (info != null) { OnProjectAdded(info); return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath); } else { return(null, projectReferences, targetPath); } }
private Document AddDocumentToProject(string filePath, string language, string projectName) { var project = CurrentSolution.Projects.FirstOrDefault(p => p.Name == projectName && p.Language == language); if (project == null) { var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), projectName, projectName, language); OnManagedProjectAdded(projectInfo); project = CurrentSolution.GetProject(projectInfo.Id); } var docInfo = DocumentInfo.Create(DocumentId.CreateNewId(project.Id), name: Path.GetFileName(filePath), loader: new FileTextLoader(filePath, null), filePath: filePath); OnDocumentAdded(docInfo); return(CurrentSolution.GetDocument(docInfo.Id)); }
public async Task <(Project project, List <string> projectReferences, string targetPath)> ReevaluateProject(IProject project) { var proj = project as OmniSharpProject; var buildHost = _buildNodes.Take(); var(info, projectReferences, targetPath) = await buildHost.LoadProject(project.Solution.CurrentDirectory, project.Location, proj.RoslynProject.Id); _buildNodes.Add(buildHost); if (info != null) { return(CurrentSolution.GetProject(info.Id), projectReferences, targetPath); } else { return(null, projectReferences, targetPath); } }
protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptions options) { if (projectId == null) { throw new ArgumentNullException(nameof(projectId)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService <IParseOptionsService>(); Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); string newVersion = parseOptionsService.GetLanguageVersion(options); GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); foreach (string configurationName in (object[])project.ConfigurationManager.ConfigurationRowNames) { switch (hostProject.Language) { case LanguageNames.CSharp: var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)project.ConfigurationManager .ConfigurationRow(configurationName).Item(1).Object; if (newVersion != csharpProperties.LanguageVersion) { csharpProperties.LanguageVersion = newVersion; } break; case LanguageNames.VisualBasic: throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); } } }
protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text) { var document = GetDocument(id); if (document == null) { return; } bool isOpen; var filePath = document.FilePath; var data = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen); // Guard against already done changes in linked files. // This shouldn't happen but the roslyn merging seems not to be working correctly in all cases :/ if (document.GetLinkedDocumentIds().Length > 0 && isOpen && !(text.GetType().FullName == "Microsoft.CodeAnalysis.Text.ChangedText")) { return; } SourceText formerText; if (changedFiles.TryGetValue(filePath, out formerText)) { if (formerText.Length == text.Length && formerText.ToString() == text.ToString()) { return; } } changedFiles [filePath] = text; Projection projection = null; foreach (var entry in ProjectionList) { var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath)); if (p != null) { filePath = entry.File.FilePath; projection = p; break; } } SourceText oldFile; if (!isOpen || !document.TryGetText(out oldFile)) { oldFile = new MonoDevelopSourceText(data); } var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList(); int delta = 0; if (!isOpen) { delta = ApplyChanges(projection, data, changes); var formatter = CodeFormatterService.GetFormatter(data.MimeType); var mp = GetMonoProject(CurrentSolution.GetProject(id.ProjectId)); string currentText = data.Text; foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } string str; if (change.NewText.Length == 0) { str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length)); } data.ReplaceText(startOffset, change.NewText.Length, str); } data.Save(); OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue); FileService.NotifyFileChanged(filePath); } else { var formatter = CodeFormatterService.GetFormatter(data.MimeType); var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0); if (documentContext != null) { var editor = (TextEditor)data; using (var undo = editor.OpenUndoGroup()) { delta = ApplyChanges(projection, data, changes); foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } if (change.NewText.Length == 0) { formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length)); } } } } OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue); Runtime.RunInMainThread(() => { if (IdeApp.Workbench != null) { foreach (var w in IdeApp.Workbench.Documents) { w.StartReparseThread(); } } }); } }
/// <inheritdoc /> public void UpdateProjectReferences(ProjectId projectId, IEnumerable <ProjectReference> references) { var roslynProject = CurrentSolution.GetProject(projectId); roslynProject = roslynProject.WithProjectReferences(references); }
protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text) { var document = GetDocument(id); if (document == null) { return; } bool isOpen; var filePath = document.FilePath; Projection projection = null; foreach (var entry in ProjectionList) { var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath)); if (p != null) { filePath = entry.File.FilePath; projection = p; break; } } var data = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen); var oldFile = isOpen ? document.GetTextAsync().Result : new MonoDevelopSourceText(data); var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList(); int delta = 0; if (!isOpen) { delta = ApplyChanges(projection, data, changes); var formatter = CodeFormatterService.GetFormatter(data.MimeType); var mp = GetMonoProject(CurrentSolution.GetProject(id.ProjectId)); string currentText = data.Text; foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } string str; if (change.NewText.Length == 0) { str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length)); } data.ReplaceText(startOffset, change.NewText.Length, str); } data.Save(); OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue); FileService.NotifyFileChanged(filePath); } else { var formatter = CodeFormatterService.GetFormatter(data.MimeType); var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0); if (documentContext != null) { var editor = (TextEditor)data; using (var undo = editor.OpenUndoGroup()) { delta = ApplyChanges(projection, data, changes); foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } if (change.NewText.Length == 0) { formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length)); } } } } OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue); Runtime.RunInMainThread(() => { if (IdeApp.Workbench != null) { foreach (var w in IdeApp.Workbench.Documents) { w.StartReparseThread(); } } }); } }