private async Task<Solution> RenameFields(Solution solution, DocumentId documentId, int count, CancellationToken cancellationToken) { Solution oldSolution = null; for (int i = 0; i < count; i++) { oldSolution = solution; var semanticModel = await solution.GetDocument(documentId).GetSemanticModelAsync(cancellationToken); var root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken); var declaration = root.GetAnnotatedNodes(s_markerAnnotation).ElementAt(i); var fieldSymbol = (IFieldSymbol)semanticModel.GetDeclaredSymbol(declaration, cancellationToken); var newName = GetNewFieldName(fieldSymbol); // Can happen with pathologically bad field names like _ if (newName == fieldSymbol.Name) { continue; } solution = await Renamer.RenameSymbolAsync(solution, fieldSymbol, newName, solution.Workspace.Options, cancellationToken).ConfigureAwait(false); solution = await CleanSolutionAsync(solution, oldSolution, cancellationToken); } return solution; }
private static async Task <GenerationResult> GenerateAsync(bool withRegeneration, IUnitTestGeneratorOptions options, Solution solution, GenerationItem generationItem, SemanticModel semanticModel) { GenerationResult result; if (File.Exists(generationItem.TargetFileName)) { var documentIds = solution.GetDocumentIdsWithFilePath(generationItem.TargetFileName); if (documentIds.FirstOrDefault() is DocumentId targetDocumentId) { var targetDocument = solution.GetDocument(targetDocumentId); var targetSemanticModel = await targetDocument.GetSemanticModelAsync().ConfigureAwait(true); result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, targetSemanticModel, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true); } else { result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, null, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true); } } else { result = await CoreGenerator.Generate(semanticModel, generationItem.SourceSymbol, null, withRegeneration, options, generationItem.NamespaceTransform).ConfigureAwait(true); } return(result); }
private async Task<Solution> RenameFields(Solution solution, DocumentId documentId, int count, CancellationToken cancellationToken) { Solution oldSolution = null; for (int i = 0; i < count; i++) { oldSolution = solution; var semanticModel = await solution.GetDocument(documentId).GetSemanticModelAsync(cancellationToken); var root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken); var declaration = root.GetAnnotatedNodes(s_markerAnnotation).ElementAt(i); // Make note, VB represents "fields" marked as "WithEvents" as properties, so don't be // tempted to treat this as a IFieldSymbol. We only need the name, so ISymbol is enough. var fieldSymbol = semanticModel.GetDeclaredSymbol(declaration, cancellationToken); var newName = GetNewFieldName(fieldSymbol); // Can happen with pathologically bad field names like _ if (newName == fieldSymbol.Name) { continue; } solution = await Renamer.RenameSymbolAsync(solution, fieldSymbol, newName, solution.Workspace.Options, cancellationToken).ConfigureAwait(false); solution = await CleanSolutionAsync(solution, oldSolution, cancellationToken); } return solution; }
private static async Task<IEnumerable<CodeAction>> GetFixesAsync(Solution solution, CodeFixProvider codeFixProvider, Diagnostic diagnostic) { List<CodeAction> codeActions = new List<CodeAction>(); await codeFixProvider.RegisterCodeFixesAsync(new CodeFixContext(solution.GetDocument(diagnostic.Location.SourceTree), diagnostic, (a, d) => codeActions.Add(a), CancellationToken.None)); return codeActions; }
private static async Task<Document> ChangeTypeAccessibilityInDocumentAsync(Solution solution, SyntaxTokenList newAccessibilityModifiers, Location typeLocation, CancellationToken cancellationToken) { var document = solution.GetDocument(typeLocation.SourceTree); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = ChangeTypeAccessibilityInSyntaxRoot(syntaxRoot, newAccessibilityModifiers, typeLocation, cancellationToken); return document.WithSyntaxRoot(newRoot); }
private static async Task<Solution> FixDocumentAsync(Solution solution, DocumentId documentId, ImmutableArray<Diagnostic> diagnostics, string codeActionEquivalenceKey, CancellationToken cancellationToken) { if (diagnostics.IsEmpty) { return solution; } string equivalenceKey = nameof(SA1412CodeFixProvider) + "." + diagnostics[0].Properties[SA1412StoreFilesAsUtf8.EncodingProperty]; if (codeActionEquivalenceKey != equivalenceKey) { return solution; } Document document = solution.GetDocument(documentId); return await SA1412CodeFixProvider.GetTransformedSolutionAsync(document, cancellationToken).ConfigureAwait(false); }
public static IEnumerable<Location> GetPreferredSourceLocations(Solution solution, ISymbol symbol) { // Prefer non-generated source locations over generated ones. var sourceLocations = GetPreferredSourceLocations(symbol); var candidateLocationGroups = from c in sourceLocations let doc = solution.GetDocument(c.SourceTree) where doc != null group c by IsFileNameForGeneratedCode(doc.FilePath); var generatedSourceLocations = candidateLocationGroups.SingleOrDefault(g => g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>(); var nonGeneratedSourceLocations = candidateLocationGroups.SingleOrDefault(g => !g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>(); return nonGeneratedSourceLocations.Any() ? nonGeneratedSourceLocations : generatedSourceLocations; }
public static async Task<Solution> ReplaceNodesWithLiteralAsync(Solution solution, IEnumerable<SyntaxNodeOrToken> nodes, Func<SyntaxNodeOrToken, string> computeReplacement, CancellationToken cancellationToken) { var groupedByDocument = nodes.GroupBy(n => solution.GetDocument(n.SyntaxTree)); var updatedSolution = solution; foreach (var nodesForDocument in groupedByDocument) { var document = nodesForDocument.Key; var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken); var changes = nodesForDocument.Select(node => new TextChange(node.Span, computeReplacement(node))); var newText = syntaxRoot.GetText().WithChanges(changes); updatedSolution = updatedSolution.WithDocumentText(document.Id, newText); } return updatedSolution; }
private async Task<Solution> Format(Solution solution, bool runFormatter) { var documentIds = solution.Projects.SelectMany(p => p.DocumentIds); foreach (var id in documentIds) { var document = solution.GetDocument(id); document = await RewriteDocumentAsync(document); if (runFormatter) { document = await Formatter.FormatAsync(document); } solution = document.Project.Solution; } return solution; }
private static async Task<IEnumerable<ISymbol>> GetCalledMethodSymbolsAsync(ISymbol symbol, Solution solution, CancellationToken cancellationToken) { var symbols = new List<ISymbol>(); foreach (var reference in symbol.DeclaringSyntaxReferences) { var semanticModel = await solution.GetDocument(reference.SyntaxTree).GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); foreach (var syntaxNode in reference.GetSyntax(cancellationToken).DescendantNodes()) { cancellationToken.ThrowIfCancellationRequested(); var newSymbol = semanticModel.GetSymbolInfo(syntaxNode, cancellationToken).Symbol; if (newSymbol != null && newSymbol is IMethodSymbol && (newSymbol.CanBeReferencedByName || ((IMethodSymbol)newSymbol).MethodKind == MethodKind.Constructor)) { symbols.Add(newSymbol); } } } return symbols; }
private static async Task GenerateItemAsync(bool withRegeneration, IUnitTestGeneratorOptions options, Solution solution, GenerationItem generationItem) { var targetProject = solution.Projects.FirstOrDefault(x => string.Equals(x.Name, generationItem.Source.SourceProjectName, StringComparison.Ordinal)); var documents = solution.GetDocumentIdsWithFilePath(generationItem.Source.FilePath); var documentId = documents.FirstOrDefault(x => x.ProjectId == targetProject?.Id) ?? documents.FirstOrDefault(); if (documentId == null) { throw new InvalidOperationException("Could not find document in solution with file path '" + generationItem.Source.FilePath + "'"); } var document = solution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(true); var tree = await semanticModel.SyntaxTree.GetRootAsync().ConfigureAwait(true); if (!tree.DescendantNodes().OfType <ClassDeclarationSyntax>().Any() && !tree.DescendantNodes().OfType <StructDeclarationSyntax>().Any()) { return; } var result = await GenerateAsync(withRegeneration, options, solution, generationItem, semanticModel).ConfigureAwait(true); generationItem.TargetContent = result.FileContent; foreach (var asset in result.RequiredAssets) { generationItem.RequiredAssets.Add(asset); } foreach (var reference in result.AssemblyReferences) { if (!generationItem.AssemblyReferences.Any(x => string.Equals(x.Name, reference.Name, StringComparison.OrdinalIgnoreCase))) { generationItem.AssemblyReferences.Add(reference); } } }
/// <summary> /// 現在選択している型を取得します。 /// </summary> private async Task <INamedTypeSymbol> GetSelectedTypeSymbolAsync(Microsoft.CodeAnalysis.Solution solution) { var activeDoc = _dte.ActiveDocument; if (activeDoc == null) { return(null); } var docId = solution.GetDocumentIdsWithFilePath(activeDoc.FullName).FirstOrDefault(); if (docId == null) { return(null); } var doc = solution.GetDocument(docId); var selection = (TextSelection)activeDoc.Selection; var position = (selection.ActivePoint.AbsoluteCharOffset - 1) + (selection.CurrentLine - 1); var symbol = await SymbolFinder.FindSymbolAtPositionAsync(doc, position); return(FindTypeSymbol(symbol)); }
async void TryStartRenameSession (Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { var changedDocuments = GetChangedDocuments (newSolution, oldSolution); foreach (var documentId in changedDocuments) { var document = newSolution.GetDocument (documentId); var root = await document.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); SyntaxToken? renameTokenOpt = root.GetAnnotatedNodesAndTokens (RenameAnnotation.Kind) .Where (s => s.IsToken) .Select (s => s.AsToken ()) .Cast<SyntaxToken?> () .FirstOrDefault (); if (renameTokenOpt.HasValue) { var latestDocument = workspace.CurrentSolution.GetDocument (documentId); var latestModel = await latestDocument.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false); var latestRoot = await latestDocument.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); Application.Invoke (delegate { try { var node = latestRoot.FindNode (renameTokenOpt.Value.Parent.Span, false, false); if (node == null) return; var info = latestModel.GetSymbolInfo (node); var sym = info.Symbol ?? latestModel.GetDeclaredSymbol (node); if (sym != null) new MonoDevelop.Refactoring.Rename.RenameRefactoring ().Rename (sym); } catch (Exception ex) { LoggingService.LogError ("Error while renaming " + renameTokenOpt.Value.Parent, ex); } }); return; } } }
async Task TryStartRenameSession (Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { var changedDocuments = GetChangedDocuments (newSolution, oldSolution); foreach (var documentId in changedDocuments) { var document = newSolution.GetDocument (documentId); var root = await document.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); SyntaxToken? renameTokenOpt = root.GetAnnotatedNodesAndTokens (RenameAnnotation.Kind) .Where (s => s.IsToken) .Select (s => s.AsToken ()) .Cast<SyntaxToken?> () .FirstOrDefault (); if (renameTokenOpt.HasValue) { var latestDocument = workspace.CurrentSolution.GetDocument (documentId); var latestModel = await latestDocument.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false); var latestRoot = await latestDocument.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); await Runtime.RunInMainThread (async delegate { try { var node = latestRoot.FindNode (renameTokenOpt.Value.Parent.Span, false, false); if (node == null) return; var info = latestModel.GetSymbolInfo (node); var sym = info.Symbol ?? latestModel.GetDeclaredSymbol (node); if (sym != null) { await new MonoDevelop.Refactoring.Rename.RenameRefactoring ().Rename (sym); } else { var links = new List<TextLink> (); var link = new TextLink ("name"); link.AddLink (new TextSegment (node.Span.Start, node.Span.Length)); links.Add (link); var oldVersion = editor.Version; editor.StartTextLinkMode (new TextLinkModeOptions (links, (arg) => { //If user cancel renaming revert changes if (!arg.Success) { var textChanges = editor.Version.GetChangesTo (oldVersion).ToList (); foreach (var v in textChanges) { editor.ReplaceText (v.Offset, v.RemovalLength, v.InsertedText); } } })); } } catch (Exception ex) { LoggingService.LogError ("Error while renaming " + renameTokenOpt.Value.Parent, ex); } }); return; } } }
private async Task <TestGenerationContext> CollectTestGenerationContextAsync( ProjectItemSummary selectedFile, string targetProjectNamespace, TestFramework testFramework, MockFramework mockFramework, IBoilerplateSettings settings) { Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution; DocumentId documentId = solution.GetDocumentIdsWithFilePath(selectedFile.FilePath).FirstOrDefault(); if (documentId == null) { throw new InvalidOperationException("Could not find document in solution with file path " + selectedFile.FilePath); } var document = solution.GetDocument(documentId); SyntaxNode root = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); SyntaxNode firstClassLikeDeclaration = root.DescendantNodes().FirstOrDefault(node => { var kind = node.Kind(); return(kind == SyntaxKind.ClassDeclaration || kind == SyntaxKind.StructDeclaration || kind == (SyntaxKind)9063); // record - Cannot update CodeAnalysis library because it's not found in VS 2019 }); if (firstClassLikeDeclaration == null) { throw new InvalidOperationException("Could not find class, struct or record declaration."); } if (firstClassLikeDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword)) { throw new InvalidOperationException("Cannot unit test an abstract class."); } SyntaxToken classIdentifierToken = firstClassLikeDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); if (classIdentifierToken == default(SyntaxToken)) { throw new InvalidOperationException("Could not find class identifier."); } object namespaceDeclarationSyntax = null; // 8842 is NamespaceDeclaration // 8845 is FileScopedNamespaceDeclaration // We would normally look for a node descended from BaseNamespaceDeclarationSyntax, but we don't have that type defined in the v1 Microsoft.CodeAnalysis DLL. // We can fix this once we are building against a higher version and can drop support for VS 2019. if (!TypeUtilities.TryGetParentSyntax(firstClassLikeDeclaration, (syntaxNode) => { return(syntaxNode.RawKind == 8842 || syntaxNode.RawKind == 8845); }, out namespaceDeclarationSyntax)) { throw new InvalidOperationException("Could not find class namespace."); } // Find property injection types var injectableProperties = new List <InjectableProperty>(); // We need to get the name via reflection since the DLL we are building against does not have the BaseNamespaceDeclarationSyntax or FileScopedNamespaceDeclarationSyntax types. string qualifiedNamespaceString = namespaceDeclarationSyntax.GetType().GetProperty("Name").GetValue(namespaceDeclarationSyntax, null).ToString(); string classFullName = qualifiedNamespaceString + "." + classIdentifierToken; INamedTypeSymbol classType = semanticModel.Compilation.GetTypeByMetadataName(classFullName); foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers())) { if (member.Kind == SymbolKind.Property) { IPropertySymbol property = (IPropertySymbol)member; foreach (AttributeData attribute in property.GetAttributes()) { if (PropertyInjectionAttributeNames.Contains(attribute.AttributeClass.ToString())) { var injectableProperty = InjectableProperty.TryCreateInjectableProperty(property.Name, property.Type.ToString(), mockFramework); if (injectableProperty != null) { injectableProperties.Add(injectableProperty); } } } } } string className = classIdentifierToken.ToString(); // Find constructor injection types List <InjectableType> constructorInjectionTypes = new List <InjectableType>(); SyntaxNode constructorDeclaration = firstClassLikeDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration); if (constructorDeclaration != null) { constructorInjectionTypes.AddRange( GetParameterListNodes(constructorDeclaration) .Select(node => InjectableType.TryCreateInjectableTypeFromParameterNode(node, semanticModel, mockFramework))); } // Find public method declarations IList <MethodDescriptor> methodDeclarations = new List <MethodDescriptor>(); foreach (MethodDeclarationSyntax methodDeclaration in firstClassLikeDeclaration.ChildNodes().Where( n => n.Kind() == SyntaxKind.MethodDeclaration && ((MethodDeclarationSyntax)n).Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)))) { var parameterList = GetParameterListNodes(methodDeclaration).ToList(); var parameterTypes = GetArgumentDescriptors(parameterList, semanticModel, mockFramework); var attributeList = GetAttributeListNodes(methodDeclaration); var isAsync = methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)) || DoesReturnTask(methodDeclaration); var hasReturnType = !DoesReturnNonGenericTask(methodDeclaration) && !DoesReturnVoid(methodDeclaration); string returnType = methodDeclaration.ReturnType.ToFullString(); methodDeclarations.Add(new MethodDescriptor(methodDeclaration.Identifier.Text, parameterTypes, isAsync, hasReturnType, returnType, attributeList)); } string unitTestNamespace; string relativePath = this.GetRelativePath(selectedFile); if (string.IsNullOrEmpty(relativePath)) { unitTestNamespace = targetProjectNamespace; } else { List <string> defaultNamespaceParts = targetProjectNamespace.Split('.').ToList(); List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts); unitTestNamespaceParts.AddRange(relativePath.Split('\\')); unitTestNamespace = string.Join(".", unitTestNamespaceParts); } List <InjectableType> injectedTypes = new List <InjectableType>(injectableProperties); injectedTypes.AddRange(constructorInjectionTypes.Where(t => t != null)); GenerateMockNames(injectedTypes); return(new TestGenerationContext( mockFramework, testFramework, document, settings, unitTestNamespace, className, qualifiedNamespaceString, injectableProperties, constructorInjectionTypes, injectedTypes, methodDeclarations)); }
private ObjectReference GetObservedSyntaxTreeRootAsync(Solution solution, DocumentId documentId) { var observedTree = solution.GetDocument(documentId).GetSyntaxRootAsync().Result; return new ObjectReference(observedTree); }
private void TestRecoverableSyntaxTree(Solution sol, DocumentId did) { // get it async and wait for it to get GC'd var observed = GetObservedSyntaxTreeRootAsync(sol, did); StopObservingAndWaitForReferenceToGo(observed); var doc = sol.GetDocument(did); // access the tree & root again (recover it) var tree = doc.GetSyntaxTreeAsync().Result; // this should cause reparsing var root = tree.GetRoot(); // prove that the new root is correctly associated with the tree Assert.Equal(tree, root.SyntaxTree); // reset the syntax root, to make it 'refactored' by adding an attribute var newRoot = doc.GetSyntaxRootAsync().Result.WithAdditionalAnnotations(SyntaxAnnotation.ElasticAnnotation); var doc2 = doc.Project.Solution.WithDocumentSyntaxRoot(doc.Id, newRoot, PreservationMode.PreserveValue).GetDocument(doc.Id); // get it async and wait for it to get GC'd var observed2 = GetObservedSyntaxTreeRootAsync(doc2.Project.Solution, did); StopObservingAndWaitForReferenceToGo(observed2); // access the tree & root again (recover it) var tree2 = doc2.GetSyntaxTreeAsync().Result; // this should cause deserialization var root2 = tree2.GetRoot(); // prove that the new root is correctly associated with the tree Assert.Equal(tree2, root2.SyntaxTree); }
private static ImmutableDictionary<Document, ImmutableArray<Diagnostic>> GetDocumentDiagnosticsMappedToNewSolution(ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentDiagnosticsToFixMap, Solution newSolution, string language) { ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Builder builder = null; foreach (var kvp in documentDiagnosticsToFixMap) { if (kvp.Key.Project.Language != language) { continue; } var document = newSolution.GetDocument(kvp.Key.Id); if (document != null) { builder = builder ?? ImmutableDictionary.CreateBuilder<Document, ImmutableArray<Diagnostic>>(); builder.Add(document, kvp.Value); } } return builder != null ? builder.ToImmutable() : ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Empty; }
/// <summary> /// Get the document in this project with the specified syntax tree. /// </summary> public Document?GetDocument(SyntaxTree?syntaxTree) => _solution.GetDocument(syntaxTree, this.Id);
public static async Task<IEnumerable<ModifiedFileResponse>> GetFileChangesAsync(Solution newSolution, Solution oldSolution, string newFileDirectory, bool wantTextChanges) { var changes = new Dictionary<string, ModifiedFileResponse>(); var solutionChanges = newSolution.GetChanges(oldSolution); foreach (var projectChange in solutionChanges.GetProjectChanges()) { foreach (var changedDocumentId in projectChange.GetAddedDocuments()) { var document = newSolution.GetDocument(changedDocumentId); var source = await document.GetTextAsync(); var modifiedFileResponse = new ModifiedFileResponse(document.Name); var change = new LinePositionSpanTextChange(); change.NewText = source.ToString(); var newPath = Path.Combine(newFileDirectory, document.Name); modifiedFileResponse.FileName = newPath; modifiedFileResponse.Changes = new[] { change }; changes[newPath] = modifiedFileResponse; // This is a little weird. The added document doesn't have a filepath // and we need one so that future operations on this document work var id = DocumentId.CreateNewId(document.Project.Id); var version = VersionStamp.Create(); var documentInfo = DocumentInfo.Create(id, document.Name, filePath: newPath, loader: TextLoader.From(TextAndVersion.Create(source, version))); var workspace = newSolution.Workspace as OmnisharpWorkspace; workspace.RemoveDocument(changedDocumentId); workspace.AddDocument(documentInfo); } foreach (var changedDocumentId in projectChange.GetChangedDocuments()) { var changedDocument = newSolution.GetDocument(changedDocumentId); ModifiedFileResponse modifiedFileResponse; var filePath = changedDocument.FilePath; if (!changes.TryGetValue(filePath, out modifiedFileResponse)) { modifiedFileResponse = new ModifiedFileResponse(filePath); changes[filePath] = modifiedFileResponse; } if (!wantTextChanges) { var changedText = await changedDocument.GetTextAsync(); modifiedFileResponse.Buffer = changedText.ToString(); } else { var originalDocument = oldSolution.GetDocument(changedDocumentId); IEnumerable<TextChange> textChanges; textChanges = await changedDocument.GetTextChangesAsync(originalDocument); var linePositionSpanTextChanges = await LinePositionSpanTextChange.Convert(originalDocument, textChanges); modifiedFileResponse.Changes = modifiedFileResponse.Changes != null ? modifiedFileResponse.Changes.Union(linePositionSpanTextChanges) : linePositionSpanTextChanges; } } } return changes.Values; }
private bool TryGetNavigationAPIRequiredArguments( ISymbol symbol, Solution solution, out IVsHierarchy hierarchy, out uint itemID, out IVsSymbolicNavigationNotify navigationNotify, out string rqname) { AssertIsForeground(); hierarchy = null; navigationNotify = null; rqname = null; itemID = (uint)VSConstants.VSITEMID.Nil; if (!symbol.Locations.Any()) { return false; } var sourceLocations = symbol.Locations.Where(loc => loc.IsInSource); if (!sourceLocations.Any()) { return false; } var documents = sourceLocations.Select(loc => solution.GetDocument(loc.SourceTree)).WhereNotNull(); if (!documents.Any()) { return false; } // We can only pass one itemid to IVsSymbolicNavigationNotify, so prefer itemids from // documents we consider to be "generated" to give external language services the best // chance of participating. var generatedCodeRecognitionService = solution.Workspace.Services.GetService<IGeneratedCodeRecognitionService>(); var generatedDocuments = documents.Where(d => generatedCodeRecognitionService.IsGeneratedCode(d)); var documentToUse = generatedDocuments.FirstOrDefault() ?? documents.First(); if (!TryGetVsHierarchyAndItemId(documentToUse, out hierarchy, out itemID)) { return false; } navigationNotify = hierarchy as IVsSymbolicNavigationNotify; if (navigationNotify == null) { return false; } rqname = LanguageServices.RQName.From(symbol); return rqname != null; }
private IList<SourceReferenceTreeItem> CreateReferenceItems( Solution solution, HashSet<ValueTuple<Document, TextSpan>> uniqueLocations, IEnumerable<Location> locations, int commonPathElements) { var referenceItems = new List<SourceReferenceTreeItem>(); foreach (var location in locations) { if (!location.IsInSource) { continue; } var document = solution.GetDocument(location.SourceTree); var sourceSpan = location.SourceSpan; if (!IsValidSourceLocation(document, sourceSpan)) { continue; } if (uniqueLocations.Add(new ValueTuple<Document, TextSpan>(document, sourceSpan))) { referenceItems.Add(new SourceReferenceTreeItem( document, sourceSpan, Glyph.Reference.GetGlyphIndex(), commonPathElements)); } } var linkedReferences = referenceItems.GroupBy(r => r.DisplayText.ToLowerInvariant()).Where(g => g.Count() > 1).SelectMany(g => g); foreach (var linkedReference in linkedReferences) { linkedReference.AddProjectNameDisambiguator(); } referenceItems.Sort(); return referenceItems; }
private static Document GetDocument(Solution solution, string fname) { var docId = solution.GetDocumentIdsWithFilePath(fname).First(); var doc = solution.GetDocument(docId); return doc; }
private async Task <TestGenerationContext> CollectTestGenerationContextAsync( ProjectItemSummary selectedFile, string targetProjectNamespace, TestFramework testFramework, MockFramework mockFramework) { Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution; DocumentId documentId = solution.GetDocumentIdsWithFilePath(selectedFile.FilePath).FirstOrDefault(); if (documentId == null) { throw new InvalidOperationException("Could not find document in solution with file path " + selectedFile.FilePath); } var document = solution.GetDocument(documentId); SyntaxNode root = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); SyntaxNode firstClassDeclaration = root.DescendantNodes().FirstOrDefault(node => node.Kind() == SyntaxKind.ClassDeclaration); if (firstClassDeclaration == null) { throw new InvalidOperationException("Could not find class declaration."); } if (firstClassDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword)) { throw new InvalidOperationException("Cannot unit test an abstract class."); } SyntaxToken classIdentifierToken = firstClassDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); if (classIdentifierToken == default(SyntaxToken)) { throw new InvalidOperationException("Could not find class identifier."); } NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!TypeUtilities.TryGetParentSyntax(firstClassDeclaration, out namespaceDeclarationSyntax)) { throw new InvalidOperationException("Could not find class namespace."); } // Find property injection types var injectableProperties = new List <InjectableProperty>(); string classFullName = namespaceDeclarationSyntax.Name + "." + classIdentifierToken; INamedTypeSymbol classType = semanticModel.Compilation.GetTypeByMetadataName(classFullName); foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers())) { if (member.Kind == SymbolKind.Property) { IPropertySymbol property = (IPropertySymbol)member; foreach (AttributeData attribute in property.GetAttributes()) { if (PropertyInjectionAttributeNames.Contains(attribute.AttributeClass.ToString())) { var injectableProperty = InjectableProperty.TryCreateInjectableProperty(property.Name, property.Type.ToString(), mockFramework); if (injectableProperty != null) { injectableProperties.Add(injectableProperty); } } } } } string className = classIdentifierToken.ToString(); // Find constructor injection types List <InjectableType> constructorInjectionTypes = new List <InjectableType>(); SyntaxNode constructorDeclaration = firstClassDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration); if (constructorDeclaration != null) { constructorInjectionTypes.AddRange( GetParameterListNodes(constructorDeclaration) .Select(node => InjectableType.TryCreateInjectableTypeFromParameterNode(node, semanticModel, mockFramework))); } // Find public method declarations IList <MethodDescriptor> methodDeclarations = new List <MethodDescriptor>(); foreach (MethodDeclarationSyntax methodDeclaration in firstClassDeclaration.ChildNodes().Where( n => n.Kind() == SyntaxKind.MethodDeclaration && ((MethodDeclarationSyntax)n).Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)))) { var parameterList = GetParameterListNodes(methodDeclaration).ToList(); var parameterTypes = GetArgumentDescriptors(parameterList, semanticModel, mockFramework); var isAsync = methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)) || DoesReturnTask(methodDeclaration); var hasReturnType = !DoesReturnNonGenericTask(methodDeclaration) && !DoesReturnVoid(methodDeclaration); methodDeclarations.Add(new MethodDescriptor(methodDeclaration.Identifier.Text, parameterTypes, isAsync, hasReturnType)); } string unitTestNamespace; string relativePath = this.GetRelativePath(selectedFile); if (string.IsNullOrEmpty(relativePath)) { unitTestNamespace = targetProjectNamespace; } else { List <string> defaultNamespaceParts = targetProjectNamespace.Split('.').ToList(); List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts); unitTestNamespaceParts.AddRange(relativePath.Split('\\')); unitTestNamespace = string.Join(".", unitTestNamespaceParts); } List <InjectableType> injectedTypes = new List <InjectableType>(injectableProperties); injectedTypes.AddRange(constructorInjectionTypes.Where(t => t != null)); GenerateMockNames(injectedTypes); return(new TestGenerationContext( mockFramework, testFramework, document, unitTestNamespace, className, namespaceDeclarationSyntax.Name.ToString(), injectableProperties, constructorInjectionTypes, injectedTypes, methodDeclarations)); }
private static Dictionary<DocumentId, List<ClassDeclarationSyntax>> GetDocumentIdClassDeclarationMapping( List<ClassDeclarationSyntax> classDeclarations, Solution currentSolution) { var mapping = new Dictionary<DocumentId, List<ClassDeclarationSyntax>>(); foreach (var classDeclaration in classDeclarations) { var documentId = currentSolution.GetDocument(classDeclaration.SyntaxTree).Id; if (!mapping.ContainsKey(documentId)) { mapping.Add(documentId, new List<ClassDeclarationSyntax>()); } mapping[documentId].Add(classDeclaration); } return mapping; }
/// <summary> /// Get the position of where a given local variable is defined considering there could be multiple variables with the same name in method body. /// For example, in "int M() { { int foo = 0; ...} { int foo = 1; ...} }", /// the return value for the first "foo" would be 0 while the value for the second one would be 1. /// It will be used to create a node with LocalVariableIndex for a non-zero value. /// In the above example, hence, a node id for the first "foo" would look like (... Member=M LocalVariable=bar) /// but an id for the second "foo" would be (... Member=M LocalVariable=bar LocalVariableIndex=1) /// </summary> private static async Task<int> GetLocalVariableIndexAsync(ISymbol symbol, Solution solution, CancellationToken cancellationToken) { int pos = 0; foreach (var reference in symbol.ContainingSymbol.DeclaringSyntaxReferences) { var currentNode = reference.GetSyntax(cancellationToken); // For VB, we have to ask its parent to get local variables within this method body // since DeclaringSyntaxReferences return statement rather than enclosing block. if (currentNode != null && symbol.Language == LanguageNames.VisualBasic) { currentNode = currentNode.Parent; } if (currentNode != null) { Document document = solution.GetDocument(currentNode.SyntaxTree); if (document == null) { continue; } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); foreach (var node in currentNode.DescendantNodes()) { ISymbol current = semanticModel.GetDeclaredSymbol(node, cancellationToken); if (current != null && current.Name == symbol.Name && (current.Kind == SymbolKind.Local || current.Kind == SymbolKind.RangeVariable)) { if (!current.Equals(symbol)) { pos++; } else { return pos; } } } } } throw ExceptionUtilities.Unreachable; }
private bool IsValidSourceLocation(Location location, Solution solution) { if (!location.IsInSource) { return false; } var document = solution.GetDocument(location.SourceTree); return IsValidSourceLocation(document, location.SourceSpan); }
public Solution SafelyRefactorSolution(Solution solution, Document document, int index) { var numInitialErrors = solution.CompilationErrorCount(); var oldErrors = solution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(a => a.Id); var oldSolution = solution; try { solution = ExecuteRefactoring(document, solution, index); var oldFile= document.GetTextAsync().Result; var newFile = solution.GetDocument(document.Id).GetTextAsync().Result; if (solution.CompilationErrorCount() > numInitialErrors) { Fail.Info("{0}", document.FilePath); Fail.Info("{0}\r\n*************************************************************************************************", oldFile); Fail.Info("{0}\r\n=================================================================================================", newFile); Fail.Error("=============================================SOLUTIONERRORS======================================================="); foreach ( var diagnostic in solution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error && !oldErrors.Any(a=> a.Equals(d.Id)))) { Fail.Error("{0}", diagnostic); } Fail.Error("========================================================================================================================="); CompilationError = true; RefactoredSolution = solution; solution = oldSolution; } else { Success.Info("{0}", document.FilePath); Success.Info("{0}\r\n*************************************************************************************************", oldFile); Success.Info("{0}\r\n=================================================================================================", newFile); RefactoredSolution = solution; NumMethodSymbolLookups += SemanticModelExtensions.NumMethodSymbolLookups; SemanticModelExtensions.ResetSymbolLookupCounter(); } } catch (RefactoringException e) { Logger.Error("Refactoring failed: index={0}: {1}: {2}", index, e.Message, e); solution = oldSolution; RefactoringExceptionWasThrown = true; } catch (NotImplementedException e) { Logger.Error("Not implemented: index={0}: {1}: {2}", index, e.Message, e); solution = oldSolution; NotImplementedExceptionWasThrown = true; } catch (PreconditionException e) { Logger.Error("Precondition failed: {0}: {1}", e.Message, e); solution = oldSolution; PreconditionFailed = true; } catch (Exception e) { Logger.Error("Unhandled exception while refactoring: index={0}: {1}\n{2}", index, e.Message, e); solution = oldSolution; OtherExceptionWasThrown = true; } return solution; }
public Document?GetDocument(SyntaxTree?syntaxTree) { return(_solution.GetDocument(syntaxTree, this.Id)); }
public static Document GetDocumentByFilePath(this Solution solution, string fullName) { return(solution.GetDocumentIdsWithFilePath(fullName) .Select(p => solution.GetDocument(p)) .FirstOrDefault()); }
public virtual async Task<Solution> TryMergeFixesAsync(Solution oldSolution, IEnumerable<CodeAction> codeActions, CancellationToken cancellationToken) { var changedDocumentsMap = new Dictionary<DocumentId, Document>(); Dictionary<DocumentId, List<Document>> documentsToMergeMap = null; foreach (var codeAction in codeActions) { cancellationToken.ThrowIfCancellationRequested(); // TODO: Parallelize GetChangedSolutionInternalAsync for codeActions ImmutableArray<CodeActionOperation> operations = await codeAction.GetPreviewOperationsAsync(cancellationToken).ConfigureAwait(false); ApplyChangesOperation singleApplyChangesOperation = null; foreach (var operation in operations) { ApplyChangesOperation applyChangesOperation = operation as ApplyChangesOperation; if (applyChangesOperation == null) { continue; } if (singleApplyChangesOperation != null) { // Already had an ApplyChangesOperation; only one is supported. singleApplyChangesOperation = null; break; } singleApplyChangesOperation = applyChangesOperation; } if (singleApplyChangesOperation == null) { continue; } var changedSolution = singleApplyChangesOperation.ChangedSolution; var solutionChanges = changedSolution.GetChanges(oldSolution); // TODO: Handle added/removed documents // TODO: Handle changed/added/removed additional documents var documentIdsWithChanges = solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()); foreach (var documentId in documentIdsWithChanges) { cancellationToken.ThrowIfCancellationRequested(); var document = changedSolution.GetDocument(documentId); Document existingDocument; if (changedDocumentsMap.TryGetValue(documentId, out existingDocument)) { if (existingDocument != null) { changedDocumentsMap[documentId] = null; var documentsToMerge = new List<Document>(); documentsToMerge.Add(existingDocument); documentsToMerge.Add(document); documentsToMergeMap = documentsToMergeMap ?? new Dictionary<DocumentId, List<Document>>(); documentsToMergeMap[documentId] = documentsToMerge; } else { documentsToMergeMap[documentId].Add(document); } } else { changedDocumentsMap[documentId] = document; } } } var currentSolution = oldSolution; foreach (var kvp in changedDocumentsMap) { cancellationToken.ThrowIfCancellationRequested(); var document = kvp.Value; if (document != null) { var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); currentSolution = currentSolution.WithDocumentText(kvp.Key, documentText); } } if (documentsToMergeMap != null) { var mergedDocuments = new ConcurrentDictionary<DocumentId, SourceText>(); var documentsToMergeArray = documentsToMergeMap.ToImmutableArray(); var mergeTasks = new Task[documentsToMergeArray.Length]; for (int i = 0; i < documentsToMergeArray.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); var kvp = documentsToMergeArray[i]; var documentId = kvp.Key; var documentsToMerge = kvp.Value; var oldDocument = oldSolution.GetDocument(documentId); mergeTasks[i] = Task.Run(async () => { var appliedChanges = (await documentsToMerge[0].GetTextChangesAsync(oldDocument, cancellationToken).ConfigureAwait(false)).ToList(); foreach (var document in documentsToMerge.Skip(1)) { cancellationToken.ThrowIfCancellationRequested(); appliedChanges = await TryAddDocumentMergeChangesAsync( oldDocument, document, appliedChanges, cancellationToken).ConfigureAwait(false); } var oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var newText = oldText.WithChanges(appliedChanges); mergedDocuments.TryAdd(documentId, newText); }); } await Task.WhenAll(mergeTasks).ConfigureAwait(false); foreach (var kvp in mergedDocuments) { cancellationToken.ThrowIfCancellationRequested(); currentSolution = currentSolution.WithDocumentText(kvp.Key, kvp.Value); } } return currentSolution; }
internal async Task <LinkedFileMergeSessionResult> MergeDiffsAsync( IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken ) { var sessionInfo = new LinkedFileDiffMergingSessionInfo(); var linkedDocumentGroupsWithChanges = _solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()) .GroupBy( d => _oldSolution.GetDocument(d).FilePath, StringComparer.OrdinalIgnoreCase ); var linkedFileMergeResults = new List <LinkedFileMergeResult>(); var updatedSolution = _newSolution; foreach (var linkedDocumentsWithChanges in linkedDocumentGroupsWithChanges) { var documentInNewSolution = _newSolution.GetDocument( linkedDocumentsWithChanges.First() ); // Ensure the first document in the group is the first in the list of var allLinkedDocuments = documentInNewSolution .GetLinkedDocumentIds() .Add(documentInNewSolution.Id); if (allLinkedDocuments.Length == 1) { continue; } SourceText mergedText; if (linkedDocumentsWithChanges.Count() > 1) { var mergeGroupResult = await MergeLinkedDocumentGroupAsync( allLinkedDocuments, linkedDocumentsWithChanges, sessionInfo, mergeConflictHandler, cancellationToken ) .ConfigureAwait(false); linkedFileMergeResults.Add(mergeGroupResult); mergedText = mergeGroupResult.MergedSourceText; } else { mergedText = await _newSolution .GetDocument(linkedDocumentsWithChanges.Single()) .GetTextAsync(cancellationToken) .ConfigureAwait(false); } foreach (var documentId in allLinkedDocuments) { updatedSolution = updatedSolution.WithDocumentText(documentId, mergedText); } } return(new LinkedFileMergeSessionResult(updatedSolution, linkedFileMergeResults)); }
private ObjectReference GetObservedTextAsync(Solution solution, DocumentId documentId, string expectedText = null) { var observedText = solution.GetDocument(documentId).GetTextAsync().Result; if (expectedText != null) { Assert.Equal(expectedText, observedText.ToString()); } return new ObjectReference(observedText); }
private async Task <string> GenerateUnitTestContentsFromFileAsync(string inputFilePath) { Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution; DocumentId documentId = solution.GetDocumentIdsWithFilePath(inputFilePath).FirstOrDefault(); if (documentId == null) { this.HandleError("Could not find document in solution with file path " + inputFilePath); } var document = solution.GetDocument(documentId); SyntaxNode root = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); SyntaxNode firstClassDeclaration = root.DescendantNodes().FirstOrDefault(node => node.Kind() == SyntaxKind.ClassDeclaration); if (firstClassDeclaration == null) { this.HandleError("Could not find class declaration."); } if (firstClassDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword)) { this.HandleError("Cannot unit test an abstract class."); } SyntaxToken classIdentifierToken = firstClassDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); if (classIdentifierToken == null) { this.HandleError("Could not find class identifier."); } NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!Utilities.TryGetParentSyntax(firstClassDeclaration, out namespaceDeclarationSyntax)) { this.HandleError("Could not find class namespace."); } // Find property injection types var injectableProperties = new List <InjectableProperty>(); string classFullName = namespaceDeclarationSyntax.Name + "." + classIdentifierToken; INamedTypeSymbol classType = semanticModel.Compilation.GetTypeByMetadataName(classFullName); foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers())) { if (member.Kind == SymbolKind.Property) { IPropertySymbol property = (IPropertySymbol)member; foreach (AttributeData attribute in property.GetAttributes()) { if (attribute.AttributeClass.ToString() == "Microsoft.Practices.Unity.DependencyAttribute") { injectableProperties.Add(new InjectableProperty(property.Name, property.Type.Name, property.Type.ContainingNamespace.ToString())); } } } } this.className = classIdentifierToken.ToString(); // Find constructor injection types var constructorInjectionTypes = new List <InjectableType>(); SyntaxNode constructorDeclaration = firstClassDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration); if (constructorDeclaration != null) { SyntaxNode parameterListNode = constructorDeclaration.ChildNodes().First(n => n.Kind() == SyntaxKind.ParameterList); var parameterNodes = parameterListNode.ChildNodes().Where(n => n.Kind() == SyntaxKind.Parameter); foreach (SyntaxNode node in parameterNodes) { SyntaxNode identifierNode = node.ChildNodes().First(n => n.Kind() == SyntaxKind.IdentifierName); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(identifierNode); constructorInjectionTypes.Add( new InjectableType( symbolInfo.Symbol.Name, symbolInfo.Symbol.ContainingNamespace.ToString())); } } string unitTestNamespace; string defaultNamespace = this.SelectedProject.Project.Properties.Item("DefaultNamespace").Value as string; if (string.IsNullOrEmpty(this.relativePath)) { unitTestNamespace = defaultNamespace; } else { List <string> defaultNamespaceParts = defaultNamespace.Split('.').ToList(); List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts); unitTestNamespaceParts.AddRange(this.relativePath.Split('\\')); unitTestNamespace = string.Join(".", unitTestNamespaceParts); } return(this.GenerateUnitTestContents( unitTestNamespace, this.className, namespaceDeclarationSyntax.Name.ToString(), injectableProperties, constructorInjectionTypes)); }
private async Task<Solution> CleanSolutionDocument(Solution solution, DocumentId documentId, CancellationToken cancellationToken) { var document = solution.GetDocument(documentId); var syntaxNode = await document.GetSyntaxRootAsync(cancellationToken); if (syntaxNode == null) { return solution; } var newNode = RemoveRenameAnnotations(syntaxNode); return solution.WithDocumentSyntaxRoot(documentId, newNode); }
private void AddActiveStatements(Solution solution, ShellInterop.ENC_ACTIVE_STATEMENT[] vsActiveStatements) { Debug.Assert(_activeMethods.Count == 0); Debug.Assert(_exceptionRegions.Count == 0); foreach (var vsActiveStatement in vsActiveStatements) { log.DebugWrite("+AS[{0}]: {1} {2} {3} {4} '{5}'", vsActiveStatement.id, vsActiveStatement.tsPosition.iStartLine, vsActiveStatement.tsPosition.iStartIndex, vsActiveStatement.tsPosition.iEndLine, vsActiveStatement.tsPosition.iEndIndex, vsActiveStatement.filename); // TODO (tomat): // Active statement is in user hidden code. The only information that we have from the debugger // is the method token. We don't need to track the statement (it's not in user code anyways), // but we should probably track the list of such methods in order to preserve their local variables. // Not sure what's exactly the scenario here, perhaps modifying async method/iterator? // Dev12 just ignores these. if (vsActiveStatement.posType != TEXT_POSITION_ACTIVE_STATEMENT) { continue; } var flags = (ActiveStatementFlags)vsActiveStatement.ASINFO; // Finds a document id in the solution with the specified file path. DocumentId documentId = solution.GetDocumentIdsWithFilePath(vsActiveStatement.filename) .Where(dId => dId.ProjectId == _vsProject.Id).SingleOrDefault(); if (documentId != null) { var document = solution.GetDocument(documentId); Debug.Assert(document != null); SourceText source = document.GetTextAsync(default(CancellationToken)).Result; LinePositionSpan lineSpan = vsActiveStatement.tsPosition.ToLinePositionSpan(); // If the PDB is out of sync with the source we might get bad spans. var sourceLines = source.Lines; if (lineSpan.End.Line >= sourceLines.Count || sourceLines.GetPosition(lineSpan.End) > sourceLines[sourceLines.Count - 1].EndIncludingLineBreak) { log.Write("AS out of bounds (line count is {0})", source.Lines.Count); continue; } SyntaxNode syntaxRoot = document.GetSyntaxRootAsync(default(CancellationToken)).Result; var analyzer = document.Project.LanguageServices.GetService<IEditAndContinueAnalyzer>(); s_pendingActiveStatements.Add(new VsActiveStatement( this, vsActiveStatement.id, document.Id, new ActiveStatementSpan(flags, lineSpan))); bool isLeaf = (flags & ActiveStatementFlags.LeafFrame) != 0; var ehRegions = analyzer.GetExceptionRegions(source, syntaxRoot, lineSpan, isLeaf); for (int i = 0; i < ehRegions.Length; i++) { _exceptionRegions.Add(new VsExceptionRegion( vsActiveStatement.id, i, vsActiveStatement.methodToken, ehRegions[i])); } } _activeMethods.Add(vsActiveStatement.methodToken); } }
private static Document GetDocumentToVerify(DocumentId expectedChangedDocumentId, Solution oldSolution, Solution newSolution) { Document document; // If the expectedChangedDocumentId is not mentioned then we expect only single document to be changed if (expectedChangedDocumentId == null) { var projectDifferences = SolutionUtilities.GetSingleChangedProjectChanges(oldSolution, newSolution); var documentId = projectDifferences.GetChangedDocuments().FirstOrDefault() ?? projectDifferences.GetAddedDocuments().FirstOrDefault(); Assert.NotNull(documentId); document = newSolution.GetDocument(documentId); } else { // This method obtains only the document changed and does not check the project state. document = newSolution.GetDocument(expectedChangedDocumentId); } return document; }
/// <summary> /// Gets the active <see cref="Document"/> the user is currently working in. May be null if /// there is no active document or the active document is not in this <paramref name="solution"/>. /// </summary> public static Document GetActiveDocument(this IDocumentTrackingService service, Solution solution) { // Note: GetDocument checks that the DocId is contained in the solution, and returns null if not. return(solution.GetDocument(service.TryGetActiveDocument())); }
// The rename process and annotation for the bookkeeping is performed in one-step private async Task<Solution> AnnotateAndRename_WorkerAsync( Solution originalSolution, Solution partiallyRenamedSolution, HashSet<DocumentId> documentIdsToRename, IEnumerable<RenameLocation> renameLocations, RenamedSpansTracker renameSpansTracker, bool replacementTextValid) { try { foreach (var documentId in documentIdsToRename.ToList()) { _cancellationToken.ThrowIfCancellationRequested(); // We try to rewrite all locations that are not candidate locations. If there is only one location // it must be the correct one (the symbol is ambiguous to something else) and we always try to rewrite it. var document = originalSolution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false); var originalSyntaxRoot = await semanticModel.SyntaxTree.GetRootAsync(_cancellationToken).ConfigureAwait(false); // Get all rename locations for the current document. var allTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && !l.IsRenameInStringOrComment && (renameLocations.Count() == 1 || !l.IsCandidateLocation || l.IsMethodGroupReference)) .ToDictionary(l => l.Location.SourceSpan); // All textspan in the document documentId, that requires rename in String or Comment var stringAndCommentTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && l.IsRenameInStringOrComment) .GroupBy(l => l.ContainingLocationForStringOrComment) .Select(g => g.Key) .ToSet(); var conflictLocationSpans = _conflictLocations .Where(t => t.DocumentId == documentId) .Select(t => t.ComplexifiedSpan).ToSet(); // Annotate all nodes with a RenameLocation annotations to record old locations & old referenced symbols. // Also annotate nodes that should get complexified (nodes for rename locations + conflict locations) var parameters = new RenameRewriterParameters( _renamedSymbolDeclarationAnnotation, document, semanticModel, originalSyntaxRoot, _replacementText, _originalText, _possibleNameConflicts, allTextSpansInSingleSourceTree, stringAndCommentTextSpansInSingleSourceTree, conflictLocationSpans, originalSolution, _renameLocationSet.Symbol, replacementTextValid, renameSpansTracker, _optionSet, _renameAnnotations, _cancellationToken); var renameRewriterLanguageService = document.Project.LanguageServices.GetService<IRenameRewriterLanguageService>(); var newRoot = renameRewriterLanguageService.AnnotateAndRename(parameters); if (newRoot == originalSyntaxRoot) { // Update the list for the current phase, some files with strings containing the original or replacement // text may have been filtered out. documentIdsToRename.Remove(documentId); } else { partiallyRenamedSolution = partiallyRenamedSolution.WithDocumentSyntaxRoot(documentId, newRoot, PreservationMode.PreserveIdentity); } } return partiallyRenamedSolution; } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
/// <summary> /// Get a read only collection of all the unique visible documents in the workspace that are /// contained within <paramref name="solution"/>. /// </summary> public static ImmutableArray <Document> GetVisibleDocuments(this IDocumentTrackingService service, Solution solution) => service.GetVisibleDocuments() .Select(d => solution.GetDocument(d)) .WhereNotNull() .Distinct() .ToImmutableArray();
private static async Task<Solution> ChangeTypeAccessibilityInSolutionAsync(Solution solution, SyntaxTokenList newAccessibilityModifiers, IEnumerable<Location> typeLocations, CancellationToken cancellationToken) { var updatedSolution = solution; var typeLocationsGroupedByDocument = typeLocations.GroupBy(location => solution.GetDocument(location.SourceTree)); foreach(var typeLocationsWithinDocument in typeLocationsGroupedByDocument) { var document = typeLocationsWithinDocument.Key; var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = ChangeTypesAccessibilityInSyntaxRoot(syntaxRoot, newAccessibilityModifiers, typeLocationsWithinDocument); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, newRoot); } return updatedSolution; }
private AbstractTreeItem ConvertToDefinitionItem( Solution solution, ReferencedSymbol referencedSymbol, Location location, Glyph glyph) { if (!location.IsInSource) { return referencedSymbol.Locations.Any() ? new MetadataDefinitionTreeItem( solution.Workspace, referencedSymbol.Definition, referencedSymbol.Locations.First().Document.Project.Id, glyph.GetGlyphIndex()) : null; } var document = solution.GetDocument(location.SourceTree); var sourceSpan = location.SourceSpan; if (!IsValidSourceLocation(document, sourceSpan)) { return null; } return new SourceDefinitionTreeItem(document, sourceSpan, referencedSymbol.Definition, glyph.GetGlyphIndex()); }