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;
            }
Exemplo n.º 2
0
        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;
		}
Exemplo n.º 8
0
        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;
        }
Exemplo n.º 10
0
        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;
        }
Exemplo n.º 11
0
        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));
        }
Exemplo n.º 16
0
 private ObjectReference GetObservedSyntaxTreeRootAsync(Solution solution, DocumentId documentId)
 {
     var observedTree = solution.GetDocument(documentId).GetSyntaxRootAsync().Result;
     return new ObjectReference(observedTree);
 }
Exemplo n.º 17
0
        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;
        }
Exemplo n.º 19
0
 /// <summary>
 /// Get the document in this project with the specified syntax tree.
 /// </summary>
 public Document?GetDocument(SyntaxTree?syntaxTree)
 => _solution.GetDocument(syntaxTree, this.Id);
Exemplo n.º 20
0
        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;
        }
Exemplo n.º 22
0
        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;
        }
Exemplo n.º 23
0
		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;
        }
Exemplo n.º 26
0
        /// <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;
        }
Exemplo n.º 27
0
        private bool IsValidSourceLocation(Location location, Solution solution)
        {
            if (!location.IsInSource)
            {
                return false;
            }

            var document = solution.GetDocument(location.SourceTree);
            return IsValidSourceLocation(document, location.SourceSpan);
        }
Exemplo n.º 28
0
        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;
        }
Exemplo n.º 29
0
 public Document?GetDocument(SyntaxTree?syntaxTree)
 {
     return(_solution.GetDocument(syntaxTree, this.Id));
 }
Exemplo n.º 30
0
 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;
        }
Exemplo n.º 32
0
        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));
        }
Exemplo n.º 33
0
        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;
        }
Exemplo n.º 38
0
 /// <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()));
 }
Exemplo n.º 39
0
            // 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;
                }
            }
Exemplo n.º 40
0
 /// <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;
        }
Exemplo n.º 42
0
        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());
        }