Example #1
0
        public async void Execute(ISolution solution, ITextControl textControl)
        {
            if (this.ExistingProjectFile != null)
            {
                await ShowProjectFile(solution, this.ExistingProjectFile, null);

                return;
            }

            using (ReadLockCookie.Create())
            {
                string         testClassName;
                string         testNamespace;
                string         testFileName;
                IProjectFolder testFolder;
                Template       testFileTemplate;

                using (var cookie = solution.CreateTransactionCookie(DefaultAction.Rollback, this.Text, NullProgressIndicator.Create()))
                {
                    var declaration = this._provider.GetSelectedElement <ICSharpTypeDeclaration>();

                    var declaredType = declaration?.DeclaredElement;
                    if (declaredType == null)
                    {
                        return;
                    }

                    var settingsStore  = declaration.GetSettingsStore();
                    var helperSettings = ReSharperHelperSettings.GetSettings(settingsStore);

                    var testProject = this.CachedTestProject ?? this.ResolveTargetTestProject(declaration, solution, helperSettings);
                    if (testProject == null)
                    {
                        return;
                    }

                    var classNamespaceParts = TrimDefaultProjectNamespace(declaration.GetProject().NotNull(), declaredType.GetContainingNamespace().QualifiedName);
                    var testFolderLocation  = classNamespaceParts.Aggregate(testProject.Location, (current, part) => current.Combine(part));

                    testNamespace = StringUtil.MakeFQName(testProject.GetDefaultNamespace(), StringUtil.MakeFQName(classNamespaceParts));

                    testFolder = testProject.GetOrCreateProjectFolder(testFolderLocation, cookie);
                    if (testFolder == null)
                    {
                        return;
                    }

                    testClassName = declaredType.ShortName + helperSettings.TestClassNameSuffix;
                    testFileName  = testClassName + ".cs";

                    testFileTemplate = StoredTemplatesProvider.Instance.EnumerateTemplates(settingsStore, TemplateApplicability.File).FirstOrDefault(t => t.Description == TemplateDescription);

                    cookie.Commit(NullProgressIndicator.Create());
                }

                if (testFileTemplate != null)
                {
                    await FileTemplatesManager.Instance.CreateFileFromTemplateAsync(testFileName, new ProjectFolderWithLocation(testFolder), testFileTemplate);

                    return;
                }

                var newFile = AddNewItemHelper.AddFile(testFolder, testFileName);
                if (newFile == null)
                {
                    return;
                }

                int?caretPosition = -1;
                solution.GetPsiServices()
                .Transactions.Execute(this.Text, () =>
                {
                    var psiSourceFile = newFile.ToSourceFile();

                    var csharpFile = psiSourceFile?.GetDominantPsiFile <CSharpLanguage>() as ICSharpFile;
                    if (csharpFile == null)
                    {
                        return;
                    }

                    var elementFactory = CSharpElementFactory.GetInstance(csharpFile);

                    var namespaceDeclaration = elementFactory.CreateNamespaceDeclaration(testNamespace);
                    var addedNs = csharpFile.AddNamespaceDeclarationAfter(namespaceDeclaration, null);

                    var classLikeDeclaration = (IClassLikeDeclaration)elementFactory.CreateTypeMemberDeclaration("public class $0 {}", testClassName);
                    var addedTypeDeclaration = addedNs.AddTypeDeclarationAfter(classLikeDeclaration, null) as IClassDeclaration;

                    caretPosition = addedTypeDeclaration?.Body?.GetDocumentRange().TextRange.StartOffset + 1;
                });

                await ShowProjectFile(solution, newFile, caretPosition);
            }
        }
Example #2
0
        public bool IsAvailable(IUserDataHolder cache)
        {
            this.ExistingProjectFile = null;
            this.CachedTestProject   = null;

            var classDeclaration = ClassDeclarationNavigator.GetByNameIdentifier(this._provider.GetSelectedElement <ICSharpIdentifier>());
            var declaredType     = classDeclaration?.DeclaredElement;

            if (declaredType == null)
            {
                return(false);
            }

            // Disable for nested classes.
            if (classDeclaration.GetContainingTypeDeclaration() != null)
            {
                return(false);
            }

            // TRY RESOLVE EXISTING TEST.
            var helperSettings = ReSharperHelperSettings.GetSettings(classDeclaration.GetSettingsStore());

            var testProject = this.CachedTestProject = this.ResolveTargetTestProject(classDeclaration, classDeclaration.GetSolution(), helperSettings);

            if (testProject == null)
            {
                return(false);
            }

            // Skip project if it's the same as current. This way we don't suggest to create tests in test projects.
            if (testProject.Equals(classDeclaration.GetProject()))
            {
                return(false);
            }

            var testClassNamespaceParts = MakeTestClassNamespaceParts(classDeclaration, testProject);

            if (testClassNamespaceParts == null)
            {
                return(false);
            }
            var testNamespace = StringUtil.MakeFQName(testClassNamespaceParts);

            // Resolve candidates for test classes.
            var validTestSuffixes = helperSettings.ValidTestClassNameSuffixes?.Split(',', StringSplitOptions.RemoveEmptyEntries)
                                    .Select(s => s.ToString())
                                    .Concat(helperSettings.TestClassNameSuffix)
                                    .Distinct();

            var classTypeFqnCandidates = validTestSuffixes?.Select(suffix => StringUtil.MakeFQName(testNamespace, declaredType.ShortName + suffix));

            if (classTypeFqnCandidates == null)
            {
                return(false);
            }

            var symbolsService = classDeclaration.GetPsiServices().Symbols;

            var testClass = testProject.GetPsiModules()
                            .Select(m => symbolsService.GetSymbolScope(m, false, true))
                            .SelectMany(scope => classTypeFqnCandidates.Select(scope.GetTypeElementByCLRName))
                            .FirstNotNull();

            this.ExistingProjectFile = testClass?.GetSingleOrDefaultSourceFile()?.ToProjectFile();

            return(true);
        }