mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[xtext.ui][contentAssist] More fixes for content assist parsing
This commit is contained in:
parent
6edadbd173
commit
c292366748
2 changed files with 69 additions and 10 deletions
|
@ -269,7 +269,7 @@ public abstract class AbstractContentAssistParser implements IContentAssistParse
|
|||
private String[][] getRequiredRuleNames(String ruleName, List<Integer> paramStack, AbstractElement elementToParse) {
|
||||
return requiredRuleNameComputer.getRequiredRuleNames(new RequiredRuleNameComputer.Param(ruleName, paramStack, elementToParse) {
|
||||
@Override
|
||||
protected String getBaseRuleName(AbstractElement element) {
|
||||
public String getBaseRuleName(AbstractElement element) {
|
||||
return getRuleName(element);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -18,36 +18,59 @@ import org.eclipse.xtext.Group;
|
|||
import org.eclipse.xtext.Parameter;
|
||||
import org.eclipse.xtext.ParserRule;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
import org.eclipse.xtext.xtext.ConditionEvaluator;
|
||||
import org.eclipse.xtext.xtext.RuleNames;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Computes the Antlr method names that need to be invoked to continue the
|
||||
* follow element computation for content proposals. It is used if a previous
|
||||
* round produced follow elements with a lookahead bigger than 1. The result
|
||||
* of {@link #getRequiredRuleNames(Param)} is the list of methods that need
|
||||
* need to be invoked to force the parser in one or the other direction at the
|
||||
* current decision point.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.9
|
||||
*/
|
||||
@Singleton
|
||||
public class RequiredRuleNameComputer {
|
||||
|
||||
public static abstract class Param {
|
||||
private String ruleName;
|
||||
private List<Integer> paramStack;
|
||||
private AbstractElement elementToParse;
|
||||
private static final String[][] EMPTY_ARRAY = new String[0][];
|
||||
|
||||
public static abstract class Param {
|
||||
public String ruleName;
|
||||
public List<Integer> paramStack;
|
||||
public AbstractElement elementToParse;
|
||||
|
||||
private Set<Parameter> assignedParameters;
|
||||
|
||||
protected Param(String ruleName, List<Integer> paramStack, AbstractElement elementToParse) {
|
||||
this.ruleName = ruleName;
|
||||
this.paramStack = paramStack;
|
||||
this.elementToParse = elementToParse;
|
||||
}
|
||||
|
||||
protected abstract String getBaseRuleName(AbstractElement element);
|
||||
public Set<Parameter> getAssignedParametes() {
|
||||
if (assignedParameters == null) {
|
||||
return assignedParameters = getAssignedParameters(elementToParse, paramStack);
|
||||
}
|
||||
return assignedParameters;
|
||||
}
|
||||
|
||||
public abstract String getBaseRuleName(AbstractElement element);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private RuleNames ruleNames;
|
||||
|
||||
public String[][] getRequiredRuleNames(Param param) {
|
||||
if (isFiltered(param)) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
AbstractElement elementToParse = param.elementToParse;
|
||||
String ruleName = param.ruleName;
|
||||
if (ruleName == null) {
|
||||
|
@ -56,7 +79,7 @@ public class RequiredRuleNameComputer {
|
|||
if (call.getRule() instanceof ParserRule) {
|
||||
String antlrRuleName = ruleNames.getAntlrRuleName(call.getRule());
|
||||
if (!call.getArguments().isEmpty()) {
|
||||
Set<Parameter> context = getAssignedParameters(elementToParse, param.paramStack);
|
||||
Set<Parameter> context = param.getAssignedParametes();
|
||||
Set<Parameter> arguments = getAssignedArguments(call, context);
|
||||
int config = getParameterConfig(arguments);
|
||||
antlrRuleName = ruleNames.getAntlrRuleName(call.getRule(), config);
|
||||
|
@ -64,14 +87,14 @@ public class RequiredRuleNameComputer {
|
|||
return new String[][] {{ antlrRuleName }};
|
||||
}
|
||||
}
|
||||
return new String[0][];
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
String adjustedRuleName = adjustRuleName(ruleName, param);
|
||||
if (!(GrammarUtil.isOptionalCardinality(elementToParse) || GrammarUtil.isOneOrMoreCardinality(elementToParse))) {
|
||||
return new String[][] {{ adjustedRuleName }};
|
||||
}
|
||||
if ((elementToParse.eContainer() instanceof Group)) {
|
||||
List<AbstractElement> tokens = ((Group) elementToParse.eContainer()).getElements();
|
||||
List<AbstractElement> tokens = getFilteredElements(((Group) elementToParse.eContainer()).getElements(), param);
|
||||
int idx = tokens.indexOf(elementToParse) + 1;
|
||||
if (idx != tokens.size()) {
|
||||
String secondRule = param.getBaseRuleName((AbstractElement) elementToParse.eContainer());
|
||||
|
@ -85,7 +108,35 @@ public class RequiredRuleNameComputer {
|
|||
return new String[][] {{ ruleName }};
|
||||
}
|
||||
|
||||
private String adjustRuleName(String ruleName, Param param) {
|
||||
protected List<AbstractElement> getFilteredElements(List<AbstractElement> elements, Param param) {
|
||||
List<AbstractElement> result = Lists.newArrayListWithExpectedSize(elements.size());
|
||||
for(AbstractElement element: elements) {
|
||||
if (!isFiltered(element, param)) {
|
||||
result.add(element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isFiltered(Param param) {
|
||||
return isFiltered(param.elementToParse, param);
|
||||
}
|
||||
|
||||
protected boolean isFiltered(AbstractElement canddiate, Param param) {
|
||||
if (canddiate instanceof Group) {
|
||||
Group group = (Group) canddiate;
|
||||
if (group.getGuardCondition() != null) {
|
||||
Set<Parameter> context = param.getAssignedParametes();
|
||||
ConditionEvaluator evaluator = new ConditionEvaluator(context);
|
||||
if (!evaluator.evaluate(group.getGuardCondition())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String adjustRuleName(String ruleName, Param param) {
|
||||
AbstractElement elementToParse = param.elementToParse;
|
||||
Set<Parameter> context = getAssignedParameters(elementToParse, param.paramStack);
|
||||
if (!context.isEmpty()) {
|
||||
|
@ -102,4 +153,12 @@ public class RequiredRuleNameComputer {
|
|||
return ruleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||
*/
|
||||
protected RuleNames getRuleNames() {
|
||||
return ruleNames;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue