public CodeEditorViewAdapterCSharp(AltaxoWorkspaceBase workspace, Microsoft.CodeAnalysis.DocumentId documentID, RoslynSourceTextContainerAdapter sourceText) { Workspace = workspace ?? throw new ArgumentNullException(nameof(workspace)); DocumentId = documentID ?? throw new ArgumentNullException(nameof(documentID)); SourceTextAdapter = sourceText ?? throw new ArgumentNullException(nameof(sourceText)); _roslynHost = workspace.RoslynHost; SourceTextAdapter.TextChanged += EhSourceTextAdapter_TextChanged; HighlightingColorizer = new SemanticHighlighting.SemanticHighlightingColorizer(Workspace, DocumentId); QuickInfoProvider = _roslynHost.GetService <QuickInfo.IQuickInfoProvider>(); FoldingStrategy = new SyntaxTreeFoldingStrategy(); BraceMatchingService = _roslynHost.GetService <IBraceMatchingService>(); ReferenceHighlightService = new ReferenceHighlighting.CSharp.CSharpDocumentHighlightsService(); CompletionProvider = new Completion.CodeEditorCompletionProvider(_roslynHost, Workspace, DocumentId); RenamingService = new Renaming.RenamingService(); IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy(); LiveDocumentFormatter = new LiveDocumentFormatterCSharp(); ExternalHelpProvider = new ExternalHelp.ExternalHelpProvider(); Workspace.SubscribeToDiagnosticsUpdateNotification(DocumentId, EhDiagnosticsUpdated); }
/// <summary> /// Creates a new instance of this project updated to no longer include the specified additional document. /// </summary> public Project RemoveAdditionalDocument(DocumentId documentId) { return(this.Solution.RemoveAdditionalDocument(documentId).GetProject(this.Id)); }
static void RemoveDocument(ConcurrentDictionary <DocumentId, List <DeclaredSymbolInfo> > result, Microsoft.CodeAnalysis.DocumentId documentId) { if (result.ContainsKey(documentId)) { List <DeclaredSymbolInfo> val; result.TryRemove(documentId, out val); } }
protected static ValueSource <TextAndVersion> CreateRecoverableText(TextLoader loader, DocumentId documentId, SolutionServices services) { return(new RecoverableTextAndVersion( new AsyncLazy <TextAndVersion>( asynchronousComputeFunction: cancellationToken => loader.LoadTextAsync(services.Workspace, documentId, cancellationToken), synchronousComputeFunction: cancellationToken => loader.LoadTextSynchronously(services.Workspace, documentId, cancellationToken), cacheResult: false), services.TemporaryStorage)); }
public DocumentState GetDocumentState(DocumentId documentId) { _documentStates.TryGetValue(documentId, out var state); return(state); }
public bool ContainsDocument(DocumentId documentId) { return(_documentStates.ContainsKey(documentId)); }
protected static async Task <TextAndVersion> LoadTextAsync(TextLoader loader, DocumentId documentId, SolutionServices services, bool reportInvalidDataException, CancellationToken cancellationToken) { int retries = 0; while (true) { try { using (ExceptionHelpers.SuppressFailFast()) { var result = await loader.LoadTextAndVersionAsync(services.Workspace, documentId, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return(result); } } catch (OperationCanceledException) { // if load text is failed due to a cancellation, make sure we propagate it out to the caller throw; } catch (IOException e) { if (++retries > MaxRetries) { services.Workspace.OnWorkspaceFailed(new DocumentDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message, documentId)); return(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, documentId.GetDebuggerDisplay())); } // fall out to try again } catch (InvalidDataException e) { // TODO: Adjust this behavior in the future if we add support for non-text additional files if (reportInvalidDataException) { services.Workspace.OnWorkspaceFailed(new DocumentDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message, documentId)); } return(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, documentId.GetDebuggerDisplay())); } // try again after a delay await Task.Delay(RetryDelay, cancellationToken).ConfigureAwait(false); } }
public DocumentInfo WithId(DocumentId id) { return(With(attributes: Attributes.With(id: id))); }
/// <returns>The DocumentId of the current context document attached to the textContainer, if any.</returns> private DocumentId UpdateCurrentContextMapping_NoLock(SourceTextContainer textContainer, DocumentId id) { var documentIds = this.CurrentSolution.GetRelatedDocumentIds(id); if (documentIds.Length == 0) { // no related document. remove map and return no context _bufferToDocumentInCurrentContextMap.Remove(textContainer); return null; } if (documentIds.Length == 1 && documentIds[0] == id) { // only related document is myself. remove map and return no context _bufferToDocumentInCurrentContextMap.Remove(textContainer); return null; } if (documentIds[0] != id) { // there are related documents, set first one as new context. _bufferToDocumentInCurrentContextMap[textContainer] = documentIds[0]; return documentIds[0]; } // there are multiple related documents, and first one is myself. return next one. _bufferToDocumentInCurrentContextMap[textContainer] = documentIds[1]; return documentIds[1]; }
private void UpdateCurrentContextMapping_NoLock(SourceTextContainer textContainer, DocumentId id, bool isCurrentContext) { if (isCurrentContext || !_bufferToDocumentInCurrentContextMap.ContainsKey(textContainer)) { _bufferToDocumentInCurrentContextMap[textContainer] = id; } }
internal override TextAndVersion LoadTextAndVersionSynchronously(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken) { return(TextAndVersion.Create(_container.CurrentText, _version, _filePath)); }
public override Task <TextAndVersion> LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken) { return(Task.FromResult(LoadTextAndVersionSynchronously(workspace, documentId, cancellationToken))); }
internal override TextAndVersion LoadTextAndVersionSynchronously(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken) { return(_textAndVersion); }
/// <summary> /// Load a text and a version of the document in the workspace. /// </summary> internal virtual TextAndVersion LoadTextAndVersionSynchronously(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken) { // this implementation exists in case a custom derived type does not have access to internals return(LoadTextAndVersionAsync(workspace, documentId, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken)); }
/// <summary> /// Load a text and a version of the document in the workspace. /// </summary> public abstract Task <TextAndVersion> LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken);
private SourceTextContainer GetOpenDocumentSourceTextContainer_NoLock(DocumentId documentId) { // TODO: remove linear search return(_bufferToAssociatedDocumentsMap.Where(kvp => kvp.Value.Contains(documentId)).Select(kvp => kvp.Key).FirstOrDefault()); }
/// <summary> /// Call this method to tell the host environment to change the current active context to this document. Only supported if /// <see cref="CanChangeActiveContextDocument"/> returns true. /// </summary> internal virtual void SetDocumentContext(DocumentId documentId) { throw new NotSupportedException(); }
protected static ValueSource <TextAndVersion> CreateStrongText(TextLoader loader, DocumentId documentId, SolutionServices services, bool reportInvalidDataException) { return(new AsyncLazy <TextAndVersion>( c => LoadTextAsync(loader, documentId, services, reportInvalidDataException, c), cacheResult: true)); }
protected static ValueSource <TextAndVersion> CreateRecoverableText(TextLoader loader, DocumentId documentId, SolutionServices services, bool reportInvalidDataException) { return(new RecoverableTextAndVersion( new AsyncLazy <TextAndVersion>( asynchronousComputeFunction: c => LoadTextAsync(loader, documentId, services, reportInvalidDataException, c), synchronousComputeFunction: c => LoadTextSynchronously(loader, documentId, services, reportInvalidDataException, c), cacheResult: false), services.TemporaryStorage)); }
/// <summary> /// Close the specified document in the host environment. /// </summary> public virtual void CloseDocument(DocumentId documentId) => this.CheckCanOpenDocuments();
/// <summary> /// Create a <see cref="ProjectInfo"/> structure initialized from a compilers command line arguments. /// </summary> public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory, Workspace workspace = null) { // TODO (tomat): the method may throw all sorts of exceptions. var tmpWorkspace = workspace ?? new AdhocWorkspace(DesktopMefHostServices.DefaultServices); var languageServices = tmpWorkspace.Services.GetLanguageServices(language); if (languageServices == null) { throw new ArgumentException(WorkspacesResources.UnrecognizedLanguageName); } var commandLineArgumentsFactory = languageServices.GetRequiredService <ICommandLineArgumentsFactoryService>(); var commandLineArguments = commandLineArgumentsFactory.CreateCommandLineArguments(commandLineArgs, projectDirectory, isInteractive: false); // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's var referenceResolver = new MetadataFileReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory); var referenceProvider = tmpWorkspace.Services.GetRequiredService <IMetadataService>().GetProvider(); var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory); var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths); // resolve all metadata references. var boundMetadataReferences = commandLineArguments.ResolveMetadataReferences(new AssemblyReferenceResolver(referenceResolver, referenceProvider)); var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference); if (unresolvedMetadataReferences != null) { throw new ArgumentException(string.Format(WorkspacesResources.CantResolveMetadataReference, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference)); } // resolve all analyzer references. var boundAnalyzerReferences = commandLineArguments.ResolveAnalyzerReferences(); var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference); if (unresolvedAnalyzerReferences != null) { throw new ArgumentException(string.Format(WorkspacesResources.CantResolveAnalyzerReference, ((UnresolvedAnalyzerReference)unresolvedAnalyzerReferences).Display)); } AssemblyIdentityComparer assemblyIdentityComparer; if (commandLineArguments.AppConfigPath != null) { try { using (var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read)) { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream); } } catch (Exception e) { throw new ArgumentException(string.Format(WorkspacesResources.ErrorWhileReadingSpecifiedConfigFile, e.Message)); } } else { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; } var projectId = ProjectId.CreateNewId(debugName: projectName); // construct file infos var docs = new List <DocumentInfo>(); foreach (var fileArg in commandLineArguments.SourceFiles) { var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory) ? Path.GetFullPath(fileArg.Path) : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path)); var relativePath = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath); var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath); var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : ""; var folders = isWithinProject ? GetFolders(relativePath) : null; var name = Path.GetFileName(relativePath); var id = DocumentId.CreateNewId(projectId, absolutePath); var doc = DocumentInfo.Create( id: id, name: name, folders: folders, sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular, loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding), filePath: absolutePath); docs.Add(doc); } // construct file infos for additional files. var additionalDocs = new List <DocumentInfo>(); foreach (var fileArg in commandLineArguments.AdditionalFiles) { var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory) ? Path.GetFullPath(fileArg.Path) : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path)); var relativePath = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath); var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath); var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : ""; var folders = isWithinProject ? GetFolders(relativePath) : null; var name = Path.GetFileName(relativePath); var id = DocumentId.CreateNewId(projectId, absolutePath); var doc = DocumentInfo.Create( id: id, name: name, folders: folders, sourceCodeKind: SourceCodeKind.Regular, loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding), filePath: absolutePath); additionalDocs.Add(doc); } // If /out is not specified and the project is a console app the csc.exe finds out the Main method // and names the compilation after the file that contains it. We don't want to create a compilation, // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces. // So if we don't have the /out argument we name the compilation "<anonymous>". string assemblyName = (commandLineArguments.OutputFileName != null) ? Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>"; // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname var projectInfo = ProjectInfo.Create( projectId, VersionStamp.Create(), projectName, assemblyName, language: language, compilationOptions: commandLineArguments.CompilationOptions .WithXmlReferenceResolver(xmlFileResolver) .WithAssemblyIdentityComparer(assemblyIdentityComparer) .WithStrongNameProvider(strongNameProvider) .WithMetadataReferenceResolver(new AssemblyReferenceResolver(referenceResolver, referenceProvider)), parseOptions: commandLineArguments.ParseOptions, documents: docs, additionalDocuments: additionalDocs, metadataReferences: boundMetadataReferences, analyzerReferences: boundAnalyzerReferences); return(projectInfo); }
/// <summary> /// Open the specified analyzer config document in the host environment. /// </summary> public virtual void OpenAnalyzerConfigDocument(DocumentId documentId, bool activate = true) => this.CheckCanOpenDocuments();
public bool ContainsAdditionalDocument(DocumentId documentId) { return(_additionalDocumentStates.ContainsKey(documentId)); }
/// <summary> /// Close the specified analyzer config document in the host environment. /// </summary> public virtual void CloseAnalyzerConfigDocument(DocumentId documentId) => this.CheckCanOpenDocuments();
public TextDocumentState GetAdditionalDocumentState(DocumentId documentId) { _additionalDocumentStates.TryGetValue(documentId, out var state); return(state); }
protected void ClearOpenDocument(DocumentId documentId, bool isSolutionClosing) { ClearOpenDocument(documentId); }
/// <summary> /// Open the specified additional document in the host environment. /// </summary> public virtual void OpenAdditionalDocument(DocumentId documentId, bool activate = true) { this.CheckCanOpenDocuments(); }
/// <summary> /// Close the specified additional document in the host environment. /// </summary> public virtual void CloseAdditionalDocument(DocumentId documentId) { this.CheckCanOpenDocuments(); }
static void RemoveDocument(ConcurrentDictionary <DocumentId, Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfo> > > result, Microsoft.CodeAnalysis.DocumentId documentId) { result.TryRemove(documentId, out Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfo> > val); }
/// <summary> /// Creates a new additional document in a new instance of this project. /// </summary> public TextDocument AddAdditionalDocument(string name, string text, IEnumerable <string> folders = null, string filePath = null) { var id = DocumentId.CreateNewId(this.Id); return(this.Solution.AddAdditionalDocument(id, name, text, folders, filePath).GetAdditionalDocument(id)); }