예제 #1
0
        public static Document GetDocumentForSymbol(this Compilation compilation, Solution solution, string name)
        {
            var relatedSymbols = compilation.GetSymbolsWithName(p => p == name, SymbolFilter.Type)
                                 .ToList();

            if (relatedSymbols.Count != 1)
            {
                return(null);
            }

            var symbol = relatedSymbols.First() as ITypeSymbol;

            if (symbol.TypeKind == TypeKind.Enum)
            {
                return(null);
            }

            var location = relatedSymbols
                           .Select(p => p.Locations.FirstOrDefault())
                           .FirstOrDefault();

            var docId = solution
                        .GetDocumentIdsWithFilePath(location.SourceTree.FilePath)
                        .FirstOrDefault();

            return(solution.GetDocument(docId));
        }
예제 #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);
        }
예제 #3
0
        private async Task <LinkedFileMergeResult> MergeLinkedDocumentGroupAsync(
            IEnumerable <DocumentId> allLinkedDocuments,
            IEnumerable <DocumentId> linkedDocumentGroup,
            LinkedFileDiffMergingSessionInfo sessionInfo,
            IMergeConflictHandler mergeConflictHandler,
            CancellationToken cancellationToken)
        {
            var groupSessionInfo = new LinkedFileGroupSessionInfo();

            // Automatically merge non-conflicting diffs while collecting the conflicting diffs

            var textDifferencingService = _oldSolution.Workspace.Services.GetService <IDocumentTextDifferencingService>() ?? new DefaultDocumentTextDifferencingService();
            var appliedChanges          = await textDifferencingService.GetTextChangesAsync(_oldSolution.GetDocument(linkedDocumentGroup.First()), _newSolution.GetDocument(linkedDocumentGroup.First()), cancellationToken).ConfigureAwait(false);

            var unmergedChanges = new List <UnmergedDocumentChanges>();

            foreach (var documentId in linkedDocumentGroup.Skip(1))
            {
                appliedChanges = await AddDocumentMergeChangesAsync(
                    _oldSolution.GetDocument(documentId),
                    _newSolution.GetDocument(documentId),
                    appliedChanges.ToList(),
                    unmergedChanges,
                    groupSessionInfo,
                    textDifferencingService,
                    cancellationToken).ConfigureAwait(false);
            }

            var originalDocument   = _oldSolution.GetDocument(linkedDocumentGroup.First());
            var originalSourceText = await originalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

            // Add comments in source explaining diffs that could not be merged

            IEnumerable <TextChange> allChanges;
            IList <TextSpan>         mergeConflictResolutionSpan = new List <TextSpan>();

            if (unmergedChanges.Any())
            {
                mergeConflictHandler ??= _oldSolution.GetDocument(linkedDocumentGroup.First()).GetLanguageService <ILinkedFileMergeConflictCommentAdditionService>();
                var mergeConflictTextEdits = mergeConflictHandler.CreateEdits(originalSourceText, unmergedChanges);

                allChanges = MergeChangesWithMergeFailComments(appliedChanges, mergeConflictTextEdits, mergeConflictResolutionSpan, groupSessionInfo);
            }
            else
            {
                allChanges = appliedChanges;
            }

            groupSessionInfo.LinkedDocuments      = _newSolution.GetDocumentIdsWithFilePath(originalDocument.FilePath).Length;
            groupSessionInfo.DocumentsWithChanges = linkedDocumentGroup.Count();
            sessionInfo.LogLinkedFileResult(groupSessionInfo);

            return(new LinkedFileMergeResult(allLinkedDocuments, originalSourceText.WithChanges(allChanges), mergeConflictResolutionSpan));
        }
예제 #4
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));
        }
        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 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 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));
        }
예제 #10
0
 public static Document GetDocumentByFilePath(this Solution solution, string fullName)
 {
     return(solution.GetDocumentIdsWithFilePath(fullName)
            .Select(p => solution.GetDocument(p))
            .FirstOrDefault());
 }
        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));
        }