internal static SyntaxNode Format(SyntaxNode node, IEnumerable <TextSpan> spans, Workspace workspace, OptionSet options, IEnumerable <IFormattingRule> rules, CancellationToken cancellationToken) { if (workspace == null) { throw new ArgumentNullException("workspace"); } if (node == null) { throw new ArgumentNullException("node"); } if (spans == null) { throw new ArgumentNullException("spans"); } var languageFormatter = LanguageService.GetService <ISyntaxFormattingService>(workspace, node.Language); if (languageFormatter != null) { options = options ?? WorkspaceService.GetService <IOptionService>(workspace).GetOptions(); rules = rules ?? GetDefaultFormattingRules(workspace, node.Language); return(languageFormatter.Format(node, spans, options, rules, cancellationToken).GetFormattedRoot(cancellationToken)); } else { return(node); } }
internal static IList <TextChange> GetFormattedTextChanges(SyntaxNode node, IEnumerable <TextSpan> spans, Workspace workspace, OptionSet options = null, IEnumerable <IFormattingRule> rules = null, CancellationToken cancellationToken = default(CancellationToken)) { if (workspace == null) { throw new ArgumentNullException("workspace"); } if (node == null) { throw new ArgumentNullException("node"); } var languageFormatter = LanguageService.GetService <ISyntaxFormattingService>(workspace, node.Language); if (languageFormatter != null) { options = options ?? WorkspaceService.GetService <IOptionService>(workspace).GetOptions(); rules = rules ?? GetDefaultFormattingRules(workspace, node.Language); return(languageFormatter.Format(node, spans, options, rules, cancellationToken).GetTextChanges(cancellationToken)); } else { return(SpecializedCollections.EmptyList <TextChange>()); } }
internal static MetadataReference GetOrBuildReference( Solution solution, ProjectReference projectReference, Compilation finalCompilation, VersionStamp version, CancellationToken cancellationToken) { MetadataReference reference; if (TryGetReference(solution, projectReference, finalCompilation, version, out reference)) { return(reference); } // okay, we don't have one. so create one now. // first, prepare image // * NOTE * image is cancellable, do not create it inside of canditional weak table. var service = WorkspaceService.GetService <ITemporaryStorageService>(solution.Workspace); var image = MetadataOnlyImage.Create(service, finalCompilation, cancellationToken); if (image.IsEmpty) { // unfortunately, we couldn't create one. do best effort if (TryGetReference(solution, projectReference, finalCompilation, VersionStamp.Default, out reference)) { // we have one from previous compilation!!, it might be out-of-date big time, but better than nothing. // re-use it return(reference); } } // okay, proceed with whatever image we have // now, remove existing set var mapFromBranch = cache.GetValue(solution.BranchId, createReferenceSetMap); mapFromBranch.Remove(projectReference.ProjectId); // create new one var newReferenceSet = new MetadataOnlyReferenceSet(version, image); var referenceSet = snapshotCache.GetValue(finalCompilation, _ => newReferenceSet); if (newReferenceSet != referenceSet) { // someone else has beaten us. // let image go eagarly. otherwise, finalizer in temporary storage will take care of it image.Cleanup(); // return new reference return(referenceSet.GetMetadataReference(finalCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes)); } // record it to version based cache as well. snapshot cache always has a higher priority. we don't need to check returned set here // since snapshot based cache will take care of same compilation for us. mapFromBranch.GetValue(projectReference.ProjectId, _ => referenceSet); // return new reference return(referenceSet.GetMetadataReference(finalCompilation, projectReference.Aliases, projectReference.EmbedInteropTypes)); }
protected static async Task <T> LoadAsync <T>( Document document, string persistenceName, string formatVersion, Func <ObjectReader, VersionStamp, T> readFrom, CancellationToken cancellationToken) where T : AbstractPersistableState { var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); var version = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); // attempt to load from persisted state using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) using (var stream = await storage.ReadStreamAsync(document, persistenceName, cancellationToken).ConfigureAwait(false)) { if (stream == null) { return(null); } using (var reader = new ObjectReader(stream)) { VersionStamp persistVersion; if (TryReadVersion(reader, formatVersion, out persistVersion) && VersionStamp.CanReusePersistedVersion(version, persistVersion)) { return(readFrom(reader, version)); } } } return(null); }
/// <summary> /// this is for a metadata reference in a solution /// </summary> private static async Task <SymbolTreeInfo> LoadOrCreateAsync(Solution solution, IAssemblySymbol assembly, string filePath, CancellationToken cancellationToken) { // if assembly is not from a file, just create one on the fly if (filePath == null || !File.Exists(filePath) || !FilePathUtilities.PartOfFrameworkOrReferencePaths(filePath)) { return(Create(VersionStamp.Default, assembly, cancellationToken)); } // if solution is not from a disk, just create one. if (solution.FilePath == null || !File.Exists(solution.FilePath)) { return(Create(VersionStamp.Default, assembly, cancellationToken)); } // okay, see whether we can get one from persistence service. var relativePath = FilePathUtilities.GetRelativePath(solution.FilePath, filePath); var version = VersionStamp.Create(File.GetLastWriteTimeUtc(filePath)); var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(solution.Workspace); // attempt to load from persisted state. metadata reference is solution wise information SymbolTreeInfo info; using (var storage = persistentStorageService.GetStorage(solution)) { var key = PrefixMetadataSymbolTreeInfo + relativePath; using (var stream = await storage.ReadStreamAsync(key, cancellationToken).ConfigureAwait(false)) { if (stream != null) { using (var reader = new ObjectReader(stream)) { info = ReadFrom(reader); if (info != null && VersionStamp.CanReusePersistedVersion(version, info.version)) { return(info); } } } } cancellationToken.ThrowIfCancellationRequested(); // compute it if we couldn't load it from cache info = Create(version, assembly, cancellationToken); if (info != null) { using (var stream = SerializableBytes.CreateWritableStream()) using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken)) { info.WriteTo(writer); stream.Position = 0; await storage.WriteStreamAsync(key, stream, cancellationToken).ConfigureAwait(false); } } } return(info); }
private async Task <ProjectDependencyGraph> LoadOrComputeGraphAsync(Solution solution, CancellationToken cancellationToken) { Contract.ThrowIfFalse(solution.BranchId == solution.Workspace.PrimaryBranchId); // TODO: make this async too var persistenceService = WorkspaceService.GetService <IPersistentStorageService>(solution.Workspace); ProjectDependencyGraph graph; using (var storage = persistenceService.GetStorage(solution)) using (var stream = await storage.ReadStreamAsync(PersistenceName, cancellationToken).ConfigureAwait(false)) { if (stream != null) { using (var reader = new ObjectReader(stream)) { graph = ProjectDependencyGraph.From(solution, reader, cancellationToken); if (graph != null) { return(graph); } } } } cancellationToken.ThrowIfCancellationRequested(); // do it the hard way! graph = ProjectDependencyGraph.From(solution, cancellationToken); // since we built it, we may as well save it for next time await SaveGraphAsync(graph, cancellationToken).ConfigureAwait(false); return(graph); }
/// <summary> /// this will return either regular semantic model or speculative semantic based on context. /// any feature that is involved in typing or run on UI thread should use this to take advantage of speculative semantic model /// whenever possible automatically. /// /// when using this API, semantic model should only be used to ask node inside of the given node except ones that belong to /// member signature. otherwise, it might throw if semantic model returned by this API is a speculative semantic model. /// /// also, symbols from the semantic model returned by this API might have out of date location information. /// if exact location (not relative location) is needed from symbol, regular GetSemanticModel should be used. /// </summary> public static Task <SemanticModel> GetSemanticModelForNodeAsync(this Document document, SyntaxNode node, CancellationToken cancellationToken) { var syntaxFactService = LanguageService.GetService <ISyntaxFactsService>(document); var semanticModelService = WorkspaceService.GetService <ISemanticModelService>(document.Project.Solution.Workspace); if (semanticModelService == null || syntaxFactService == null || node == null) { return(document.GetSemanticModelAsync(cancellationToken)); } return(GetSemanticModelForNodeAsync(semanticModelService, syntaxFactService, document, node, node.FullSpan, cancellationToken)); }
public static IEnumerable <ISymbol> GetRecommendedSymbolsAtPosition( SemanticModel semanticModel, int position, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default(CancellationToken)) { options = options ?? WorkspaceService.GetService <IOptionService>(workspace).GetOptions(); var languageRecommender = LanguageService.GetService <IRecommendationService>(workspace, semanticModel.Language); return(languageRecommender.GetRecommendedSymbolsAtPosition(workspace, semanticModel, position, options, cancellationToken)); }
/// <summary> /// this is for a project in a solution /// </summary> private static async Task <ValueTuple <bool, SymbolTreeInfo> > LoadOrCreateAsync(Project project, CancellationToken cancellationToken) { if (await project.IsForkedProjectWithSemanticChangesAsync(cancellationToken).ConfigureAwait(false)) { return(ValueTuple.Create(false, await CreateAsync(project, cancellationToken).ConfigureAwait(false))); } var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(project.Solution.Workspace); var version = await project.GetSemanticVersionAsync(cancellationToken).ConfigureAwait(false); // attempt to load from persisted state SymbolTreeInfo info; var succeeded = false; using (var storage = persistentStorageService.GetStorage(project.Solution)) { using (var stream = await storage.ReadStreamAsync(project, ProjectSymbolTreeInfoPersistenceName, cancellationToken).ConfigureAwait(false)) { if (stream != null) { using (var reader = new ObjectReader(stream)) { info = ReadFrom(reader); if (info != null && VersionStamp.CanReusePersistedVersion(version, info.version)) { return(ValueTuple.Create(true, info)); } } } } cancellationToken.ThrowIfCancellationRequested(); // compute it if we couldn't load it from cache info = await CreateAsync(project, cancellationToken).ConfigureAwait(false); if (info != null) { using (var stream = SerializableBytes.CreateWritableStream()) using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken)) { info.WriteTo(writer); stream.Position = 0; succeeded = await storage.WriteStreamAsync(project, ProjectSymbolTreeInfoPersistenceName, stream, cancellationToken).ConfigureAwait(false); } } } return(ValueTuple.Create(succeeded, info)); }
public static bool TryGetIdentifierLocations(Document document, VersionStamp version, string identifier, List <int> positions, CancellationToken cancellationToken) { var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) { var esentStorage = storage as ISyntaxTreeInfoPersistentStorage; if (esentStorage == null) { // basically, we don't support it. return true so that we don't try to precalcuate it return(false); } return(esentStorage.ReadIdentifierPositions(document, version, identifier, positions, cancellationToken)); } }
public BackgroundParser(Workspace workspace) { this.workspace = workspace; var taskSchedulerFactory = WorkspaceService.GetService <IWorkspaceTaskSchedulerFactory>(workspace); this.taskScheduler = taskSchedulerFactory.CreateTaskScheduler(TaskScheduler.Default); this.workspace.WorkspaceChanged += this.OnWorkspaceChanged; var editorWorkspace = workspace as Workspace; if (editorWorkspace != null) { editorWorkspace.DocumentOpened += this.OnDocumentOpened; editorWorkspace.DocumentClosed += this.OnDocumentClosed; } }
private static ValueSource <Compilation> GetCompilation(Project project, Compilation compilation) { var workspace = project.Solution.Workspace; var compilationCache = WorkspaceService.GetService <ICompilationCacheService>(workspace); if (compilationCache == null) { return(new ConstantValueSource <Compilation>(compilation)); } if (project.Solution.BranchId == workspace.PrimaryBranchId && compilationCache.Primary != null) { return(new CachedObjectSource <Compilation>(compilation, compilationCache.Primary)); } return(new ConstantValueSource <Compilation>(compilation)); }
private async Task SaveGraphAsync(ProjectDependencyGraph graph, CancellationToken cancellationToken) { Contract.ThrowIfFalse(graph.Solution.BranchId == graph.Solution.Workspace.PrimaryBranchId); using (var stream = SerializableBytes.CreateWritableStream()) using (var writer = new ObjectWriter(stream)) { graph.WriteTo(writer); stream.Position = 0; var persistenceService = WorkspaceService.GetService <IPersistentStorageService>(graph.Solution.Workspace); using (var storage = persistenceService.GetStorage(graph.Solution)) { await storage.WriteStreamAsync(PersistenceName, stream, cancellationToken).ConfigureAwait(false); } } }
protected static async Task <bool> SaveAsync <T>( Document document, string persistenceName, string formatVersion, T data, CancellationToken cancellationToken) where T : AbstractPersistableState, IObjectWritable { Contract.Requires(!await document.IsForkedDocumentWithSyntaxChangesAsync(cancellationToken).ConfigureAwait(false)); var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); // attempt to load from persisted state using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) using (var stream = SerializableBytes.CreateWritableStream()) using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken)) { data.WriteVersion(writer, formatVersion); data.WriteTo(writer); stream.Position = 0; return(await storage.WriteStreamAsync(document, persistenceName, stream, cancellationToken).ConfigureAwait(false)); } }
/// <summary> /// Finds the symbols that implement an interface or interface member. /// </summary> public static async Task <IEnumerable <ISymbol> > FindImplementationsAsync( ISymbol symbol, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken)) { // A symbol can only have implementations if it's an interface or a // method/property/event from an interface. TODO(cyrusn): Handle events once they're // exposed in the compiler layer. if (symbol is INamedTypeSymbol) { var namedTypeSymbol = (INamedTypeSymbol)symbol; var implementingTypes = await namedTypeSymbol.FindImplementingTypesAsync(solution, projects, cancellationToken).ConfigureAwait(false); return(implementingTypes.Where(IsAccessible)); } else if (symbol.IsImplementable()) { var containingType = symbol.ContainingType.OriginalDefinition; var allTypes = await containingType.FindImplementingTypesAsync(solution, projects, cancellationToken).ConfigureAwait(false); var languageServicesFactory = WorkspaceService.GetService <ILanguageServiceProviderFactory>(solution.Workspace); List <ISymbol> results = null; foreach (var t in allTypes) { foreach (var m in t.FindImplementationsForInterfaceMember(symbol, languageServicesFactory, cancellationToken)) { var s = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false) ?? m; if (IsAccessible(s)) { results = results ?? new List <ISymbol>(); results.Add(s.OriginalDefinition); } } } if (results != null) { return(results.Distinct(SymbolEquivalenceComparer.Instance)); } } return(SpecializedCollections.EmptyEnumerable <ISymbol>()); }
public static async Task <bool> IdentifierSetPrecalculatedAsync(Document document, CancellationToken cancellationToken) { var version = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) { var esentStorage = storage as ISyntaxTreeInfoPersistentStorage; if (esentStorage == null) { // basically, we don't support it. return true so that we don't try to precalcuate it return(true); } var persistedVersion = esentStorage.GetIdentifierSetVersion(document); return(VersionStamp.CanReusePersistedVersion(version, persistedVersion)); } }
public static async Task SaveIdentifierSetAsync(Document document, CancellationToken cancellationToken) { Contract.Requires(document.IsFromPrimaryBranch()); var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) { var esentStorage = storage as ISyntaxTreeInfoPersistentStorage; if (esentStorage == null) { return; } var version = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); esentStorage.WriteIdentifierLocations(document, version, root, cancellationToken); } }
public BackgroundCompiler(Workspace workspace) { this.workspace = workspace; // make a scheduler that runs on the thread pool var taskSchedulerFactory = WorkspaceService.GetService <IWorkspaceTaskSchedulerFactory>(workspace); this.compilationScheduler = taskSchedulerFactory.CreateTaskScheduler(TaskScheduler.Default); // default uses current (ideally UI/foreground scheduler) if possible this.notificationQueue = taskSchedulerFactory.CreateTaskQueue(); this.cancellationSource = new CancellationTokenSource(); this.workspace.WorkspaceChanged += this.OnWorkspaceChanged; var editorWorkspace = workspace as Workspace; if (editorWorkspace != null) { editorWorkspace.DocumentOpened += OnDocumentOpened; editorWorkspace.DocumentClosed += OnDocumentClosed; } }
/// <summary> /// this will return either regular semantic model or speculative semantic based on context. /// any feature that is involved in typing or run on UI thread should use this to take advantage of speculative semantic model /// whenever possible automatically. /// /// when using this API, semantic model should only be used to ask node inside of the given span. /// otherwise, it might throw if semantic model returned by this API is a speculative semantic model. /// /// also, symbols from the semantic model returned by this API might have out of date location information. /// if exact location (not relative location) is needed from symbol, regular GetSemanticModel should be used. /// </summary> public static async Task <SemanticModel> GetSemanticModelForSpanAsync(this Document document, TextSpan span, CancellationToken cancellationToken) { var syntaxFactService = LanguageService.GetService <ISyntaxFactsService>(document); var semanticModelService = WorkspaceService.GetService <ISemanticModelService>(document.Project.Solution.Workspace); if (semanticModelService == null || syntaxFactService == null) { return(await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false)); } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (token.Parent == null) { return(await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false)); } var node = token.Parent.AncestorsAndSelf().FirstOrDefault(a => a.FullSpan.Contains(span)); return(await GetSemanticModelForNodeAsync(semanticModelService, syntaxFactService, document, node, span, cancellationToken).ConfigureAwait(false)); }
protected static async Task <bool> PrecalculatedAsync(Document document, string persistenceName, string formatVersion, CancellationToken cancellationToken) { Contract.Requires(document.IsFromPrimaryBranch()); var persistentStorageService = WorkspaceService.GetService <IPersistentStorageService>(document.Project.Solution.Workspace); var version = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); // check whether we already have info for this document using (var storage = persistentStorageService.GetStorage(document.Project.Solution)) using (var stream = await storage.ReadStreamAsync(document, persistenceName, cancellationToken).ConfigureAwait(false)) { if (stream != null) { using (var reader = new ObjectReader(stream)) { VersionStamp persistVersion; return(TryReadVersion(reader, formatVersion, out persistVersion) && VersionStamp.CanReusePersistedVersion(version, persistVersion)); } } } return(false); }
public static IExtensionManager GetExtensionManager(this Workspace workspace) { return(WorkspaceService.GetService <IExtensionManager>(workspace)); }
protected virtual SourceText CreateText(Stream stream, Workspace workspace) { var factory = WorkspaceService.GetService <ITextFactoryService>(workspace); return(factory.CreateText(stream)); }
/// <summary> /// Find symbols for declarations that implement members of the specified interface symbol /// </summary> public static async Task <IEnumerable <ISymbol> > FindImplementedInterfaceMembersAsync( ISymbol symbol, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken)) { // Member can only implement interface members if it is an explicit member, or if it is // public and non static. if (symbol != null) { var explicitImplementations = symbol.ExplicitInterfaceImplementations(); if (explicitImplementations.Length > 0) { return(explicitImplementations); } else if ( symbol.DeclaredAccessibility == Accessibility.Public && !symbol.IsStatic && (symbol.ContainingType.TypeKind == TypeKind.Class || symbol.ContainingType.TypeKind == TypeKind.Struct)) { // Interface implementation is a tricky thing. A method may implement an interface // method, even if its containing type doesn't state that it implements the // interface. For example: // // interface IFoo { void Foo(); } // // class Base { public void Foo(); } // // class Derived : Base, IFoo { } // // In this case, Base.Foo *does* implement IFoo.Foo in the context of the type // Derived. var containingType = symbol.ContainingType.OriginalDefinition; var derivedClasses = await containingType.FindDerivedClassesAsync(solution, projects, cancellationToken).ConfigureAwait(false); var allTypes = derivedClasses.Concat(containingType); var languageServicesFactory = WorkspaceService.GetService <ILanguageServiceProviderFactory>(solution.Workspace); List <ISymbol> results = null; foreach (var type in allTypes) { foreach (var interfaceType in type.AllInterfaces) { if (interfaceType.MemberNames.Contains(symbol.Name)) { foreach (var m in interfaceType.GetMembers(symbol.Name)) { var interfaceMethod = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false) ?? m; foreach (var implementation in type.FindImplementationsForInterfaceMember(interfaceMethod, languageServicesFactory, cancellationToken)) { if (implementation != null && SymbolEquivalenceComparer.Instance.Equals(implementation.OriginalDefinition, symbol.OriginalDefinition)) { results = results ?? new List <ISymbol>(); results.Add(interfaceMethod); } } } } } } if (results != null) { return(results.Distinct(SymbolEquivalenceComparer.Instance)); } } } return(SpecializedCollections.EmptyEnumerable <ISymbol>()); }
public TService GetWorkspaceService <TService>() where TService : class, IWorkspaceService { return(WorkspaceService.GetService <TService>(this.Workspace)); }
private static bool IsGeneratedCode(Document document) { return(WorkspaceService.GetService <IGeneratedCodeRecognitionService>(document.Project.Solution.Workspace).IsGeneratedCode(document)); }
public T GetService <T>() where T : class, IWorkspaceService { return(WorkspaceService.GetService <T>(this)); }