Skip to content

Commit

Permalink
Fix #414 - add an option to match any parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Läubrich committed Jun 16, 2020
1 parent 591b3b0 commit 99a8934
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 38 deletions.
9 changes: 9 additions & 0 deletions cucumber.eclipse.editor/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,13 @@
</enabledWhen>
</page>
</extension>
<extension
point="org.eclipse.ui.propertyPages">
<page
category="cucumber.eclipse.editor.properties.main"
class="cucumber.eclipse.editor.properties.ProjectGlueCodeOptions"
id="cucumber.eclipse.editor.properties.gluecodeoptions"
name="Glue Code Options">
</page>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cucumber.eclipse.editor.properties;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ICoreRunnable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbenchPropertyPage;
import org.eclipse.ui.dialogs.PropertyPage;
import org.osgi.service.prefs.BackingStoreException;

public class ProjectGlueCodeOptions extends PropertyPage implements IWorkbenchPropertyPage {

private Button matchAllParameterButton;

private static final String NAMESPACE = "cucumber.steps.glue";
private static final String KEY_MATCH_ALL_PARAMETER = "matchAllParameter";

public ProjectGlueCodeOptions() {
}

@Override
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
GridData data = new GridData(GridData.FILL_BOTH);
data.grabExcessHorizontalSpace = true;
composite.setLayoutData(data);
matchAllParameterButton = createEnableOption(composite);
return composite;
}

private Button createEnableOption(Composite composite) {
Button button = new Button(composite, SWT.CHECK);
GridData gd = new GridData();
button.setLayoutData(gd);
gd.horizontalSpan = 2;
button.setText("Match regardless of parametertype");
button.setSelection(isMatchAllParameter(getResource()));
button.addSelectionListener(new SelectionListener() {

@Override
public void widgetSelected(SelectionEvent e) {
}

@Override
public void widgetDefaultSelected(SelectionEvent e) {

}
});
return button;
}

private IResource getResource() {
return getElement().getAdapter(IResource.class);
}

private static IEclipsePreferences getNode(IResource resource) {
ProjectScope scope = new ProjectScope(resource.getProject());
IEclipsePreferences node = scope.getNode(NAMESPACE);
return node;
}

protected void performDefaults() {
super.performDefaults();
matchAllParameterButton.setSelection(false);
}

public boolean performOk() {
IResource resource = getResource();
IEclipsePreferences node = getNode(resource);
boolean oldvalue = isMatchAllParameter(resource);
boolean newValue = matchAllParameterButton.getSelection();
if (newValue != oldvalue) {
node.putBoolean(KEY_MATCH_ALL_PARAMETER, newValue);
try {
node.flush();
} catch (BackingStoreException e) {
}
IProject project = resource.getProject();
Job.create("Rebuild of " + project.getName(), new ICoreRunnable() {

@Override
public void run(IProgressMonitor monitor) throws CoreException {
project.build(IncrementalProjectBuilder.FULL_BUILD, monitor);
}
}).schedule();
}
return true;
}

public static boolean isMatchAllParameter(IResource resource) {
IEclipsePreferences node = getNode(resource);
return node.getBoolean(KEY_MATCH_ALL_PARAMETER, false);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;

import cucumber.eclipse.editor.properties.ProjectGlueCodeOptions;
import cucumber.eclipse.steps.integration.ExpressionDefinition;
import cucumber.eclipse.steps.integration.GherkinStepWrapper;
import cucumber.eclipse.steps.integration.Glue;
import cucumber.eclipse.steps.integration.StepDefinition;
import cucumber.eclipse.steps.integration.marker.MarkerFactory;
import gherkin.I18n;
import gherkin.formatter.model.Step;
import io.cucumber.cucumberexpressions.CucumberExpression;
import io.cucumber.cucumberexpressions.CucumberExpressionException;
import io.cucumber.cucumberexpressions.Expression;
import io.cucumber.cucumberexpressions.ExpressionFactory;
Expand Down Expand Up @@ -82,10 +84,9 @@ public Set<IFile> getStepDefinitionsSources() {
/**
* Find the glue for a gherkin statement
*
* @param fromGherkinStepText
* a gherkin expression
* @return the step definition related to this gherkin step. Or, null when
* not found
* @param fromGherkinStepText a gherkin expression
* @return the step definition related to this gherkin step. Or, null when not
* found
*/
public Glue findGlue(String fromGherkinStepText) {
Entry<GherkinStepWrapper, StepDefinition> glue = null;
Expand Down Expand Up @@ -121,37 +122,28 @@ public void clean(Step step) {

if (step.getLine().equals(lineNumber)) {
this.glues.remove(gherkinStepWrapper);
clearExpressionCache(gherkinStepWrapper);
break;
}
}
getExpressionCache().clear();
}

public void clean(IResource gherkinFile) {
for (Iterator<GherkinStepWrapper> iterator = this.glues.keySet().iterator(); iterator.hasNext();) {
GherkinStepWrapper wrapper = iterator.next();
if (wrapper.getSource().equals(gherkinFile)) {
iterator.remove();
clearExpressionCache(wrapper);
}
}
}

private void clearExpressionCache(GherkinStepWrapper wrapper) {
Step step = wrapper.getStep();
if (step != null) {
getExpressionCache().remove(step);
}
getExpressionCache().clear();
}

/**
* Get the text statement of a gherkin step. For example, with the step
* "Given I love cats" will return "I love cats"
* Get the text statement of a gherkin step. For example, with the step "Given I
* love cats" will return "I love cats"
*
* @param language
* the document language
* @param expression
* a gherkin step expression
* @param language the document language
* @param expression a gherkin step expression
* @return the text part of the gherkin step expression
*/
protected String getTextStatement(String language, String expression) {
Expand All @@ -166,13 +158,11 @@ protected String getTextStatement(String language, String expression) {
}

/**
* Get a matcher to ensure text starts with a basic step keyword : Given,
* When, Then, etc
* Get a matcher to ensure text starts with a basic step keyword : Given, When,
* Then, etc
*
* @param language
* the document language
* @param text
* the text to match
* @param language the document language
* @param text the text to match
* @return a matcher
*/
private Matcher getBasicStatementMatcher(String language, String text) {
Expand Down Expand Up @@ -250,7 +240,8 @@ public synchronized StepDefinition findMatchingStep(Set<StepDefinition> stepDefi
@SuppressWarnings("restriction")
private ExpressionFactory getExpressionFactory(ExpressionDefinition expression) {
if (project != null) {
Object adapter = org.eclipse.core.internal.runtime.AdapterManager.getDefault().loadAdapter(project, ExpressionFactory.class.getName());
Object adapter = org.eclipse.core.internal.runtime.AdapterManager.getDefault().loadAdapter(project,
ExpressionFactory.class.getName());
if (adapter instanceof ExpressionFactory) {
return (ExpressionFactory) adapter;
}
Expand All @@ -267,27 +258,49 @@ private synchronized Map<StepDefinition, ParsedExpression> getExpressionCache()
return expressionCache;
}

private static final class ParsedExpression {
private final class ParsedExpression {

Expression cucumberExpression;
private Expression expression;

public ParsedExpression(StepDefinition step, ExpressionFactory factory) {
ExpressionDefinition definition = step.getExpression();
String text = definition.getText();

try {
cucumberExpression = factory.createExpression(text);
} catch (CucumberExpressionException e) {
IResource source = step.getSource();
int lineNumber = step.getLineNumber();
if (source != null) {
MarkerFactory.INSTANCE.syntaxErrorOnStepDefinition(source, e, lineNumber);
if (ProjectGlueCodeOptions.isMatchAllParameter(project)) {
String altText = text.replaceAll("(?<=\\{).*?(?=\\})", "");
try {
// check if this is a cucumber or a regexp...
Expression temporary = factory.createExpression(text);
if (temporary instanceof CucumberExpression) {
text = altText;
} else {
expression = temporary;
}
} catch (CucumberExpressionException e) {
// exception can also mean this is a cucumber expression...
text = altText;
}
}
if (expression == null) {
expression = factory.createExpression(text);
}
} catch (CucumberExpressionException e) {
createErrorMarker(step, e);
} catch (PatternSyntaxException e) {
createErrorMarker(step, e);
}
}

private void createErrorMarker(StepDefinition step, Exception e) {
IResource source = step.getSource();
int lineNumber = step.getLineNumber();
if (source != null) {
MarkerFactory.INSTANCE.syntaxErrorOnStepDefinition(source, e, lineNumber);
}
}

public boolean matches(String text) {
return cucumberExpression != null && cucumberExpression.match(text) != null;
return expression != null && expression.match(text) != null;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20150519210750/repository/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.sdk.ide" version="4.5.2.M20160212-1500"/>
<repository location="http://download.eclipse.org/releases/mars"/>
<unit id="org.eclipse.sdk.ide" version="0.0.0"/>
<repository location="http://download.eclipse.org/releases/2020-03"/>
</location>
</locations>
</target>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?><target name="targetdefinition" sequenceNumber="10">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.hamcrest.library.source" version="1.3.0.v201505072020"/>
<unit id="org.hamcrest.text" version="1.1.0.v20090501071000"/>
<unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
<unit id="org.hamcrest.integration" version="1.3.0.v201305210900"/>
<unit id="org.mockito" version="1.9.5.v201311280930"/>
<unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
<unit id="org.hamcrest.integration.source" version="1.3.0.v201305210900"/>
<unit id="org.hamcrest.generator" version="1.3.0.v201305210900"/>
<unit id="org.hamcrest" version="1.1.0.v20090501071000"/>
<unit id="org.hamcrest.generator.source" version="1.3.0.v201305210900"/>
<unit id="org.hamcrest.text.source" version="1.1.0.v20090501071000"/>
<unit id="org.mockito.source" version="1.9.5.v201311280930"/>
<unit id="org.hamcrest.library" version="1.3.0.v201505072020"/>
<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20150519210750/repository/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.sdk.ide" version="4.5.2.M20160212-1500"/>
<repository location="http://download.eclipse.org/releases/mars"/>
</location>
</locations>
</target>

0 comments on commit 99a8934

Please sign in to comment.