Skip to content

Commit

Permalink
Add support for [Scope] in completion and reference
Browse files Browse the repository at this point in the history
  • Loading branch information
Socolin committed Nov 27, 2023
1 parent 18e71ab commit 446b023
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class ScopeAttributeUtil
}

scopes ??= new List<SpecflowStepScope>(attributeInstances.Count);
scopes.Add(new SpecflowStepScope(feature, tag, scenario));
scopes.Add(new SpecflowStepScope(feature, scenario, tag));
}

return scopes;
Expand Down Expand Up @@ -103,7 +103,7 @@ ICollection<IMetadataCustomAttribute> attributeInstances
}

scopes ??= new List<SpecflowStepScope>(attributeInstances.Count);
scopes.Add(new SpecflowStepScope(feature, tag, scenario));
scopes.Add(new SpecflowStepScope(feature, scenario, tag));
}

return scopes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ protected override bool AddLookupItems(GherkinSpecificCodeCompletionContext cont

foreach (var stepDefinitionInfo in specflowStepsDefinitionsCache.GetStepAccessibleForModule(psiModule, selectedStepKind).Concat(assemblyStepDefinitionCache.GetStepAccessibleForModule(psiModule, selectedStepKind)))
{
if (!selectedStep.MatchScope(stepDefinitionInfo.Scopes))
continue;
foreach (var stepVariation in stepPatternUtil.ExpandMatchingStepPatternWithAllPossibleParameter(stepDefinitionInfo, partialStepText, fullStepText))
{
var completionText = stepVariation;
Expand Down
53 changes: 50 additions & 3 deletions src/dotnet/ReSharperPlugin.SpecflowRiderPlugin/Psi/GherkinStep.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using JetBrains.DocumentModel;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;
using JetBrains.ReSharper.Psi.Tree;
using ReSharperPlugin.SpecflowRiderPlugin.Caching.StepsDefinitions;
using ReSharperPlugin.SpecflowRiderPlugin.References;
using ReSharperPlugin.SpecflowRiderPlugin.Utils.TestOutput;

Expand Down Expand Up @@ -94,7 +96,7 @@ public string GetStepTextBeforeCaret(DocumentOffset caretLocation)
public string GetStepText(bool withStepKeyWord = false)
{
var sb = new StringBuilder();
for (var te = (TreeElement) FirstChild; te != null; te = te.nextSibling)
for (var te = (TreeElement)FirstChild; te != null; te = te.nextSibling)
{
switch (te)
{
Expand Down Expand Up @@ -126,7 +128,7 @@ public string GetStepTextForExample(IDictionary<string, string> exampleData)
{
var sb = new StringBuilder();
var previousTokenWasAParameter = false;
for (var te = (TreeElement) FirstChild; te != null; te = te.nextSibling)
for (var te = (TreeElement)FirstChild; te != null; te = te.nextSibling)
{
switch (te)
{
Expand Down Expand Up @@ -169,7 +171,7 @@ public override ReferenceCollection GetFirstClassReferences()
public string GetFirstLineText()
{
var sb = new StringBuilder();
for (var te = (TreeElement) FirstChild; te != null; te = te.nextSibling)
for (var te = (TreeElement)FirstChild; te != null; te = te.nextSibling)
{
if (te.GetTokenType() == GherkinTokenTypes.NEW_LINE)
break;
Expand All @@ -183,5 +185,50 @@ public bool Match(StepTestOutput failedStepStepsOutput)
{
return GetFirstLineText() == failedStepStepsOutput.FirstLine;
}

public bool MatchScope([CanBeNull] IReadOnlyList<SpecflowStepScope> scopes)
{
if (scopes == null)
return true;

foreach (var scope in scopes)
{
if (scope.Scenario is not null)
{
var matchScenario = GetScenarioText() == scope.Scenario;
if (!matchScenario)
continue;
}

if (scope.Feature is not null)
{
var matchFeature = GetFeatureText() == scope.Feature;
if (!matchFeature)
continue;
}

if (scope.Tag is not null)
{
var matchTag = GetEffectiveTags().Contains(scope.Tag);
if (!matchTag)
continue;
}

return true;
}
return false;
}

[CanBeNull]
public string GetFeatureText()
{
return GetContainingNode<GherkinFeature>()?.GetFeatureText();
}

[CanBeNull]
public string GetScenarioText()
{
return GetContainingNode<GherkinScenario>()?.GetScenarioText();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using JetBrains.Annotations;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Tree;

namespace ReSharperPlugin.SpecflowRiderPlugin.References;

public class GherkinStepElementAccessContext([NotNull] ITreeNode element) : ElementAccessContext(element)
{

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
Expand All @@ -25,6 +26,9 @@ public SpecflowStepDeclarationReference([NotNull] GherkinStep owner) : base(owne
}

public Regex RegexPattern { get; private set; }
public string ScenarioText { get; private set; }
public string FeatureText { get; private set; }
public IList<string> Tags { get; private set; }

public override ResolveResultWithInfo ResolveWithoutCache()
{
Expand All @@ -33,6 +37,9 @@ public override ResolveResultWithInfo ResolveWithoutCache()
var stepKind = myOwner.EffectiveStepKind;
var stepText = myOwner.GetStepText();
var psiModule = myOwner.GetPsiModule();
ScenarioText = myOwner.GetScenarioText();
FeatureText = myOwner.GetFeatureText();
Tags = myOwner.GetEffectiveTags().ToList();

var containingScenario = myOwner.GetContainingNode<IGherkinScenario>();
if (containingScenario is GherkinScenarioOutline scenarioOutline)
Expand All @@ -45,26 +52,29 @@ public override ResolveResultWithInfo ResolveWithoutCache()

foreach (var cacheEntry in cacheEntries.Where(c => c.StepKind == stepKind))
{
if (cacheEntry.Regex?.IsMatch(stepText) == true)
{
var types = psiServices.Symbols.GetTypesAndNamespacesInFile(sourceFile);
foreach (var decElement in types)
{
if (!(decElement is IClass cl))
continue;

var method = cl.GetMembers().OfType<IMethod>().FirstOrDefault(x => x.ShortName == cacheEntry.MethodName);
if (method == null)
continue;

var symbolInfo = new SymbolInfo(method);
var resolveResult = ResolveResultFactory.CreateResolveResult(symbolInfo.GetDeclaredElement(), symbolInfo.GetSubstitution());

RegexPattern = cacheEntry.Regex;
return new ResolveResultWithInfo(resolveResult, ResolveErrorType.OK);
}
}
if (!myOwner.MatchScope(cacheEntry.Scopes))
continue;
if (cacheEntry.Regex?.IsMatch(stepText) == true)
{
var types = psiServices.Symbols.GetTypesAndNamespacesInFile(sourceFile);
foreach (var decElement in types)
{
if (decElement is not IClass cl)
continue;
if (cl.GetClrName().FullName != cacheEntry.ClassFullName)
continue;

var method = cl.GetMembers().OfType<IMethod>().FirstOrDefault(x => x.ShortName == cacheEntry.MethodName);
if (method == null)
continue;

var symbolInfo = new SymbolInfo(method);
var resolveResult = ResolveResultFactory.CreateResolveResult(symbolInfo.GetDeclaredElement(), symbolInfo.GetSubstitution());

RegexPattern = cacheEntry.Regex;
return new ResolveResultWithInfo(resolveResult, ResolveErrorType.OK);
}
}
}
}

Expand All @@ -78,6 +88,8 @@ public override ResolveResultWithInfo ResolveWithoutCache()

foreach (var cacheEntry in cacheEntries.Where(c => c.StepKind == stepKind))
{
if (!myOwner.MatchScope(cacheEntry.Scopes))
continue;
if (cacheEntry.Regex?.IsMatch(stepText) == true)
{
var assemblyFile = psiAssemblyFileLoader.GetOrLoadAssembly(psiAssembly, false);
Expand Down

0 comments on commit 446b023

Please sign in to comment.