private void AddSpecflowStep(IPsiSourceFile targetFile, string classClrName, GherkinStepKind stepKind, string stepText)
        {
            var cSharpFile = targetFile.GetProject().GetCSharpFile(targetFile.DisplayName.Substring(targetFile.DisplayName.LastIndexOf('>') + 2));

            if (cSharpFile == null)
            {
                return;
            }

            foreach (var type in cSharpFile.GetChildrenInSubtrees <IClassDeclaration>())
            {
                if (!(type is IClassDeclaration classDeclaration))
                {
                    continue;
                }
                if (classDeclaration.CLRName != classClrName)
                {
                    continue;
                }
                if (classDeclaration.DeclaredElement?.GetAttributeInstances(AttributesSource.Self).All(x => x.GetAttributeType().GetClrName().FullName != "TechTalk.SpecFlow.Binding") != true)
                {
                    continue;
                }

                var factory    = CSharpElementFactory.GetInstance(classDeclaration);
                var methodName = _stepDefinitionBuilder.GetStepDefinitionMethodNameFromStepText(stepKind, stepText, _reference.IsInsideScenarioOutline());
                methodName = cSharpFile.GetPsiServices().Naming.Suggestion.GetDerivedName(methodName, NamedElementKinds.Method, ScopeKind.Common, CSharpLanguage.Instance, new SuggestionOptions(), targetFile);
                var parameters = _stepDefinitionBuilder.GetStepDefinitionParameters(stepText, _reference.IsInsideScenarioOutline());
                var pattern    = _stepDefinitionBuilder.GetPattern(stepText, _reference.IsInsideScenarioOutline());

                var attributeType     = CSharpTypeFactory.CreateType(SpecflowAttributeHelper.GetAttributeClrName(stepKind), classDeclaration.GetPsiModule());
                var formatString      = $"[$0(@\"$1\")] public void {methodName}() {{ScenarioContext.StepIsPending();}}";
                var methodDeclaration = factory.CreateTypeMemberDeclaration(formatString, attributeType, pattern.Replace("\"", "\"\"")) as IMethodDeclaration;
                if (methodDeclaration == null)
                {
                    continue;
                }
                var psiModule = classDeclaration.GetPsiModule();
                foreach (var(parameterName, parameterType) in parameters)
                {
                    methodDeclaration.AddParameterDeclarationAfter(ParameterKind.VALUE, CSharpTypeFactory.CreateType(parameterType, psiModule), parameterName, null);
                }

                IClassMemberDeclaration insertedDeclaration;
                using (new PsiTransactionCookie(type.GetPsiServices(), DefaultAction.Commit, "Generate specflow step"))
                {
                    insertedDeclaration = classDeclaration.AddClassMemberDeclaration((IClassMemberDeclaration)methodDeclaration);
                }

                var invocationExpression = insertedDeclaration.GetChildrenInSubtrees <IInvocationExpression>().FirstOrDefault();
                if (invocationExpression != null)
                {
                    invocationExpression.NavigateToNode(true);
                }
                else
                {
                    insertedDeclaration.NavigateToNode(true);
                }
            }
        }
Exemplo n.º 2
0
        public void ProcessBeforeInterior(ITreeNode element, FilteringHighlightingConsumer context)
        {
            if (!(element is IMethodDeclaration method))
            {
                return;
            }

            var psiServices  = method.GetPsiServices();
            var invalidNames = new LocalList <string>();

            foreach (var attribute in method.Attributes)
            {
                var stepKind = SpecflowAttributeHelper.GetAttributeStepKind(attribute.GetAttributeType().GetClrName());
                if (stepKind == null)
                {
                    continue;
                }

                var attributeInstance = attribute.GetAttributeInstance();
                if (attributeInstance.PositionParameterCount < 1)
                {
                    continue;
                }

                var constantValue = attributeInstance.PositionParameter(0).ConstantValue;
                if (!constantValue.IsValid())
                {
                    continue;
                }

                if (!(constantValue.Value is string stepText))
                {
                    continue;
                }

                var expectedMethodName = SpecflowStepHelper.GetMethodNameAndParameterFromStepPattern(stepKind.Value, stepText, psiServices, _daemonProcess.SourceFile, method.Params.ParameterDeclarations.Select(x => x.DeclaredName).ToList());

                if (string.Equals(method.DeclaredName, expectedMethodName, StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }

                if (method.DeclaredName.ToLowerInvariant().StartsWith(stepKind.ToString().ToLowerInvariant()))
                {
                    invalidNames.Insert(0, expectedMethodName);
                }
                else
                {
                    invalidNames.Add(expectedMethodName);
                }
            }

            if (invalidNames.Count > 0)
            {
                var expectedName = invalidNames.FirstOrDefault();
                context.AddHighlighting(new MethodNameMismatchPatternInfo(method, expectedName));
            }
        }
Exemplo n.º 3
0
        public object Build(IPsiAssembly assembly)
        {
            SpecflowStepsDefinitionsCacheEntries stepDefinitions = null;

            _psiAssemblyFileLoader.GetOrLoadAssembly(assembly, true, (psiAssembly, assemblyFile, metadataAssembly) =>
            {
                stepDefinitions = new SpecflowStepsDefinitionsCacheEntries();

                foreach (var type in metadataAssembly.GetTypes())
                {
                    if (type.CustomAttributesTypeNames.All(a => a.FullName.GetText() != SpecflowAttributeHelper.BindingAttribute.FullName))
                    {
                        continue;
                    }

                    var classCacheEntry = new SpecflowStepDefinitionCacheClassEntry(type.FullyQualifiedName, true);

                    foreach (var method in type.GetMethods().Where(x => x.IsPublic))
                    {
                        // FIXME: We should avoid adding method that are not step here (it's just using more memory)
                        var methodCacheEntry = classCacheEntry.AddMethod(method.Name);

                        for (var index = 0; index < method.CustomAttributes.Length; index++)
                        {
                            var attributeInstance = method.CustomAttributes[index];
                            if (attributeInstance.ConstructorArguments.Length == 0)
                            {
                                continue;
                            }

                            var regex = attributeInstance.ConstructorArguments[0].Value as string;
                            if (regex == null)
                            {
                                continue;
                            }


                            var attributeTypeName = method.CustomAttributesTypeNames[index].FullName.ToString();
                            if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.Given, attributeTypeName))
                            {
                                methodCacheEntry.AddStep(GherkinStepKind.Given, regex);
                            }
                            if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.When, attributeTypeName))
                            {
                                methodCacheEntry.AddStep(GherkinStepKind.When, regex);
                            }
                            if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.Then, attributeTypeName))
                            {
                                methodCacheEntry.AddStep(GherkinStepKind.Then, regex);
                            }
                        }
                    }
                    stepDefinitions.Add(classCacheEntry);
                }
            });
            return(stepDefinitions);
        }
Exemplo n.º 4
0
        private SpecflowStepDefinitionCacheClassEntry BuildBindingClassCacheEntry(IClassDeclaration classDeclaration, bool hasSpecflowBindingAttribute)
        {
            var classCacheEntry = new SpecflowStepDefinitionCacheClassEntry(classDeclaration.CLRName, hasSpecflowBindingAttribute);

            foreach (var member in classDeclaration.MemberDeclarations)
            {
                if (!(member is IMethodDeclaration methodDeclaration))
                {
                    continue;
                }

                var methodCacheEntry = classCacheEntry.AddMethod(methodDeclaration.DeclaredName);

                foreach (var attributeInstance in methodDeclaration.Attributes.Select(x => x.GetAttributeInstance()))
                {
                    if (attributeInstance.PositionParameterCount == 0)
                    {
                        continue;
                    }

                    var parameter = attributeInstance.PositionParameter(0);
                    var regex     = parameter.ConstantValue.Value as string;
                    if (regex == null)
                    {
                        continue;
                    }

                    if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.Given, attributeInstance.GetAttributeType().GetClrName()))
                    {
                        methodCacheEntry.AddStep(GherkinStepKind.Given, regex);
                    }
                    if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.When, attributeInstance.GetAttributeType().GetClrName()))
                    {
                        methodCacheEntry.AddStep(GherkinStepKind.When, regex);
                    }
                    if (SpecflowAttributeHelper.IsAttributeForKind(GherkinStepKind.Then, attributeInstance.GetAttributeType().GetClrName()))
                    {
                        methodCacheEntry.AddStep(GherkinStepKind.Then, regex);
                    }
                }
            }
            return(classCacheEntry);
        }
Exemplo n.º 5
0
        public void ProcessBeforeInterior(ITreeNode element, FilteringHighlightingConsumer context)
        {
            if (!(element is IMethodDeclaration method))
            {
                return;
            }

            var psiServices  = method.GetPsiServices();
            var invalidNames = new LocalList <string>();

            foreach (var attribute in method.Attributes)
            {
                var stepKind = SpecflowAttributeHelper.GetAttributeStepKind(attribute.GetAttributeType().GetClrName());
                if (stepKind == null)
                {
                    continue;
                }

                var attributeInstance = attribute.GetAttributeInstance();
                if (attributeInstance.PositionParameterCount < 1)
                {
                    continue;
                }

                var constantValue = attributeInstance.PositionParameter(0).ConstantValue;
                if (!constantValue.IsValid())
                {
                    continue;
                }

                if (!(constantValue.Value is string stepText))
                {
                    continue;
                }

                if (method.DeclaredElement == null)
                {
                    continue;
                }

                var expectedMethodName = _stepDefinitionBuilder.GetStepDefinitionMethodNameFromPattern(stepKind.Value, stepText, method.DeclaredElement.Parameters.SelectNotNull(x => x.ShortName).ToArray());
                expectedMethodName = psiServices.Naming.Suggestion.GetDerivedName(expectedMethodName, NamedElementKinds.Method, ScopeKind.Common, CSharpLanguage.Instance.NotNull(), new SuggestionOptions(), _daemonProcess.SourceFile);

                if (string.Equals(method.DeclaredName, expectedMethodName, StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }

                if (method.DeclaredName.ToLowerInvariant().StartsWith(stepKind.ToString().ToLowerInvariant()))
                {
                    invalidNames.Insert(0, expectedMethodName);
                }
                else
                {
                    invalidNames.Add(expectedMethodName);
                }
            }

            if (invalidNames.Count > 0)
            {
                var expectedName = invalidNames.FirstOrDefault();
                context.AddHighlighting(new MethodNameMismatchPatternInfo(method, expectedName));
            }
        }