mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
[287082] Fix: Don’t loose information about bogus cardinality
Also support /* Suppress[issueCodeSuffix] */ in Xtext grammars. https://bugs.eclipse.org/bugs/show_bug.cgi?id=287082
This commit is contained in:
parent
ce4e7824a2
commit
d7ce46fa57
39 changed files with 391 additions and 13 deletions
|
@ -269,17 +269,12 @@ public abstract class AbstractXtextTests extends Assert implements ResourceLoadH
|
|||
if (d instanceof ExceptionDiagnostic)
|
||||
fail(d.getMessage());
|
||||
}
|
||||
|
||||
for(Diagnostic d: resource.getWarnings())
|
||||
System.out.println("Resource Warning: "+d);
|
||||
|
||||
if (expectedErrors == 0 && resource.getContents().size() > 0 && shouldTestSerializer(resource)) {
|
||||
SerializerTester tester = get(SerializerTester.class);
|
||||
EObject obj = resource.getContents().get(0);
|
||||
tester.assertSerializeWithNodeModel(obj);
|
||||
tester.assertSerializeWithoutNodeModel(obj);
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,8 @@ Export-Package: org.eclipse.xtext,
|
|||
org.eclipse.xtext.validation.impl,
|
||||
org.eclipse.xtext.workspace;x-friends:="org.eclipse.xtext.xbase.ui",
|
||||
org.eclipse.xtext.xtext;x-friends:="org.eclipse.xtext.xtext.ui",
|
||||
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true
|
||||
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true,
|
||||
org.eclipse.xtext.xtext.parser;x-friends:="org.eclipse.xtext.tests"
|
||||
Require-Bundle: org.eclipse.emf.ecore.xmi;bundle-version="2.10.2";visibility:=reexport,
|
||||
org.eclipse.emf.ecore;bundle-version="2.10.2";visibility:=reexport,
|
||||
org.eclipse.emf.codegen;bundle-version="2.10.0";resolution:=optional;x-installation:=greedy,
|
||||
|
|
|
@ -62,6 +62,7 @@ AbstractToken returns AbstractElement:
|
|||
Action
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride]: Handled in CardinalityAwareEcoreFactory */
|
||||
AbstractTokenWithCardinality returns AbstractElement:
|
||||
(Assignment | AbstractTerminal) (cardinality=('?'|'*'|'+'))?
|
||||
;
|
||||
|
@ -148,6 +149,7 @@ TerminalGroup returns AbstractElement:
|
|||
TerminalToken ({Group.elements+=current} (elements+=TerminalToken)+)?
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride]: Handled in CardinalityAwareEcoreFactory */
|
||||
TerminalToken returns AbstractElement:
|
||||
TerminalTokenElement (cardinality=('?'|'*'|'+'))?
|
||||
;
|
||||
|
|
|
@ -14,7 +14,9 @@ import org.eclipse.xtext.linking.ILinker;
|
|||
import org.eclipse.xtext.linking.ILinkingDiagnosticMessageProvider;
|
||||
import org.eclipse.xtext.linking.ILinkingService;
|
||||
import org.eclipse.xtext.naming.IQualifiedNameConverter;
|
||||
import org.eclipse.xtext.parser.DefaultEcoreElementFactory;
|
||||
import org.eclipse.xtext.parser.antlr.IReferableElementsUnloader;
|
||||
import org.eclipse.xtext.parser.antlr.SyntaxErrorMessageProvider;
|
||||
import org.eclipse.xtext.parsetree.reconstr.ITokenSerializer.ICrossReferenceSerializer;
|
||||
import org.eclipse.xtext.parsetree.reconstr.ITransientValueService;
|
||||
import org.eclipse.xtext.resource.DerivedStateAwareResourceDescriptionManager;
|
||||
|
@ -48,6 +50,8 @@ import org.eclipse.xtext.xtext.XtextValidator;
|
|||
import org.eclipse.xtext.xtext.XtextValueConverters;
|
||||
import org.eclipse.xtext.xtext.ecoreInference.IXtext2EcorePostProcessor;
|
||||
import org.eclipse.xtext.xtext.ecoreInference.XtendXtext2EcorePostProcessor;
|
||||
import org.eclipse.xtext.xtext.parser.CardinalityAwareEcoreFactory;
|
||||
import org.eclipse.xtext.xtext.parser.CardinalityAwareSyntaxErrorMessageProvider;
|
||||
|
||||
import com.google.inject.Binder;
|
||||
|
||||
|
@ -164,4 +168,18 @@ public class XtextRuntimeModule extends AbstractXtextRuntimeModule {
|
|||
public Class<? extends ConfigurableIssueCodesProvider> bindConfigurableIssueCodesProvider() {
|
||||
return XtextConfigurableIssueCodes.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
public Class<? extends DefaultEcoreElementFactory> bindCardinalityAwareFactory() {
|
||||
return CardinalityAwareEcoreFactory.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
public Class<? extends SyntaxErrorMessageProvider> bindSyntaxErrorMessageProvider() {
|
||||
return CardinalityAwareSyntaxErrorMessageProvider.class;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.parser.IParseResult;
|
||||
import org.eclipse.xtext.resource.DerivedStateAwareResource;
|
||||
import org.eclipse.xtext.resource.IDerivedStateComputer;
|
||||
import org.eclipse.xtext.resource.XtextSyntaxDiagnostic;
|
||||
import org.eclipse.xtext.xtext.parser.CardinalityAwareSyntaxErrorMessageProvider;
|
||||
|
||||
/**
|
||||
* Resource implementation that instantiates the infered packages as part of the
|
||||
|
@ -62,6 +68,19 @@ public class GrammarResource extends DerivedStateAwareResource {
|
|||
return super.getWarnings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
@Override
|
||||
protected void addSyntaxDiagnostic(List<Diagnostic> diagnostics, INode node) {
|
||||
SyntaxErrorMessage syntaxErrorMessage = node.getSyntaxErrorMessage();
|
||||
if (CardinalityAwareSyntaxErrorMessageProvider.CARDINALITY_ISSUE.equals(syntaxErrorMessage.getIssueCode())) {
|
||||
super.getWarnings().add(new XtextSyntaxDiagnostic(node));
|
||||
} else {
|
||||
super.addSyntaxDiagnostic(diagnostics, node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the ecore inference as soon as someone wants to access the contents
|
||||
* of a {@link GrammarResource}.
|
||||
|
|
|
@ -34,6 +34,8 @@ import com.google.common.collect.Sets;
|
|||
*/
|
||||
public class OverriddenValueInspector extends XtextRuleInspector<Boolean, ParserRule> {
|
||||
|
||||
public static final String ISSUE_CODE = "OverriddenValueInspector.potentialOverride";
|
||||
|
||||
private Multimap<String, AbstractElement> assignedFeatures;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +50,11 @@ public class OverriddenValueInspector extends XtextRuleInspector<Boolean, Parser
|
|||
permanentlyVisited = Sets.newHashSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getIssueCode() {
|
||||
return ISSUE_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addVisited(AbstractRule rule) {
|
||||
return permanentlyVisited.add(rule) && super.addVisited(rule);
|
||||
|
|
|
@ -27,10 +27,17 @@ import org.eclipse.xtext.validation.ValidationMessageAcceptor;
|
|||
*/
|
||||
public class RuleWithoutInstantiationInspector extends XtextRuleInspector<Boolean, ParserRule> {
|
||||
|
||||
public static final String ISSUE_CODE = "RuleWithoutInstantiationInspector.noInstantiation";
|
||||
|
||||
public RuleWithoutInstantiationInspector(ValidationMessageAcceptor acceptor) {
|
||||
super(acceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getIssueCode() {
|
||||
return ISSUE_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInspect(ParserRule rule) {
|
||||
// special treatment of first rule
|
||||
|
|
|
@ -7,9 +7,17 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.emf.common.util.Diagnostic;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.diagnostics.Severity;
|
||||
import org.eclipse.xtext.documentation.IEObjectDocumentationProvider;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
|
@ -27,6 +35,9 @@ public class XtextDiagnosticConverter extends DiagnosticConverterImpl{
|
|||
@Inject
|
||||
private ILocationInFileProvider locationInFileProvider;
|
||||
|
||||
@Inject
|
||||
private IEObjectDocumentationProvider documentationProvider;
|
||||
|
||||
@Override
|
||||
protected IssueLocation getLocationData(EObject obj, EStructuralFeature structuralFeature, int index) {
|
||||
if (NodeModelUtils.getNode(obj) == null) {
|
||||
|
@ -44,4 +55,42 @@ public class XtextDiagnosticConverter extends DiagnosticConverterImpl{
|
|||
return super.getLocationData(obj, structuralFeature, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Severity getSeverity(Diagnostic diagnostic) {
|
||||
Severity result = super.getSeverity(diagnostic);
|
||||
String issueCode = getIssueCode(diagnostic);
|
||||
if (result == Severity.WARNING && issueCode != null) {
|
||||
// only warnings can be suppressed
|
||||
EObject causer = getCauser(diagnostic);
|
||||
if (causer != null) {
|
||||
if (isMarkedAsIgnored(causer, issueCode)) {
|
||||
return null;
|
||||
}
|
||||
if (!(causer instanceof AbstractRule)) {
|
||||
AbstractRule rule = GrammarUtil.containingRule(causer);
|
||||
if (rule != null && isMarkedAsIgnored(rule, issueCode)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private final Pattern afterLastDot = Pattern.compile(".*\\W(\\w+)$");
|
||||
|
||||
protected boolean isMarkedAsIgnored(EObject object, String code) {
|
||||
String documentation = documentationProvider.getDocumentation(object);
|
||||
if (documentation != null) {
|
||||
Matcher matcher = afterLastDot.matcher(code);
|
||||
if (matcher.matches()) {
|
||||
String suffix = matcher.group(1);
|
||||
if (documentation.contains("Suppress[" + suffix + "]")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,13 @@ public class XtextRuleInspector<Result, RuleType extends AbstractRule> extends X
|
|||
visitedRules = Sets.newHashSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
protected String getIssueCode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void inspect(RuleType rule) {
|
||||
if (!canInspect(rule))
|
||||
return;
|
||||
|
@ -57,11 +64,11 @@ public class XtextRuleInspector<Result, RuleType extends AbstractRule> extends X
|
|||
}
|
||||
|
||||
public void acceptError(String message, EObject object, EStructuralFeature feature) {
|
||||
acceptor.acceptError(message, object, feature, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, null);
|
||||
acceptor.acceptError(message, object, feature, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, getIssueCode());
|
||||
}
|
||||
|
||||
public void acceptWarning(String message, EObject object, EStructuralFeature feature) {
|
||||
acceptor.acceptWarning(message, object, feature, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, null);
|
||||
acceptor.acceptWarning(message, object, feature, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, getIssueCode());
|
||||
}
|
||||
|
||||
public boolean addVisited(AbstractRule rule) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.parser;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
import org.eclipse.xtext.XtextPackage;
|
||||
import org.eclipse.xtext.conversion.ValueConverterException;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.parser.DefaultEcoreElementFactory;
|
||||
|
||||
/**
|
||||
* The Xtext grammar allows to override the cardinality value by using patterns like
|
||||
* {@code (feature+=RuleCall+)?}. Usually the '?' would override the '+' and the information
|
||||
* about the '+' is completely lost. This factory will flag such patterns with a warning.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.9
|
||||
*/
|
||||
public class CardinalityAwareEcoreFactory extends DefaultEcoreElementFactory {
|
||||
|
||||
@Override
|
||||
public void set(EObject object, String feature, Object value, String ruleName, INode node) throws ValueConverterException {
|
||||
if (object instanceof AbstractElement && XtextPackage.Literals.ABSTRACT_ELEMENT__CARDINALITY.getName().equals(feature)) {
|
||||
AbstractElement casted = (AbstractElement) object;
|
||||
String knownCardinality = casted.getCardinality();
|
||||
if (knownCardinality != null) {
|
||||
String newCardinality = String.valueOf(getTokenAsStringIfPossible(value));
|
||||
if ("*".equals(newCardinality)) {
|
||||
casted.setCardinality("*");
|
||||
} else if ("*".equals(knownCardinality)) {
|
||||
// nothing to do
|
||||
} else if ("+".equals(knownCardinality)) {
|
||||
if ("?".equals(newCardinality)) {
|
||||
casted.setCardinality("*");
|
||||
}
|
||||
} else if ("?".equals(knownCardinality)) {
|
||||
if ("+".equals(newCardinality)) {
|
||||
casted.setCardinality("*");
|
||||
}
|
||||
}
|
||||
throw new MoreThanOneCardinalityException(newCardinality, casted.getCardinality(), node);
|
||||
}
|
||||
}
|
||||
super.set(object, feature, value, ruleName, node);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.parser;
|
||||
|
||||
import org.eclipse.xtext.conversion.ValueConverterException;
|
||||
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
|
||||
import org.eclipse.xtext.parser.antlr.SyntaxErrorMessageProvider;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.9
|
||||
*/
|
||||
public class CardinalityAwareSyntaxErrorMessageProvider extends SyntaxErrorMessageProvider {
|
||||
|
||||
public static final String CARDINALITY_ISSUE = "CardinalityAwareSyntaxErrorMessageProvider.overriddenCardinality";
|
||||
|
||||
@Override
|
||||
public SyntaxErrorMessage getSyntaxErrorMessage(IValueConverterErrorContext context) {
|
||||
ValueConverterException cause = context.getValueConverterException();
|
||||
if (cause instanceof MoreThanOneCardinalityException) {
|
||||
return new SyntaxErrorMessage(context.getDefaultMessage(), CARDINALITY_ISSUE);
|
||||
}
|
||||
return super.getSyntaxErrorMessage(context);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.parser;
|
||||
|
||||
import org.eclipse.xtext.conversion.ValueConverterException;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.9
|
||||
*/
|
||||
public class MoreThanOneCardinalityException extends ValueConverterException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MoreThanOneCardinalityException(String newCardinality, String mergedCardinality, INode node) {
|
||||
super(String.format("More than one cardinality was set. Merging '%s' with previously assigned cardinality to '%s'.", newCardinality, mergedCardinality),
|
||||
node, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -58,6 +58,7 @@ AbstractToken returns AbstractElement:
|
|||
Action
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
AbstractTokenWithCardinality returns AbstractElement:
|
||||
(Assignment |
|
||||
AbstractTerminal) (cardinality=('?'|'*'|'+'))?
|
||||
|
@ -129,6 +130,7 @@ TerminalGroup returns AbstractElement:
|
|||
TerminalToken ({Group.tokens+=current} (tokens+=TerminalToken)+)?
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
TerminalToken returns AbstractElement:
|
||||
TerminalTokenElement (cardinality=('?'|'*'|'+'))?
|
||||
;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*******************************************************************************/
|
||||
grammar org.eclipse.xtext.enumrules.EnumRulesTestLanguage with org.eclipse.xtext.common.Terminals
|
||||
|
||||
/* Suppress[external] */
|
||||
import "classpath:/org/eclipse/xtext/enumrules/enums.ecore"
|
||||
generate enumRulesTestLanguage "http://www.eclipse.org/2009/tmf/xtext/EnumRulesTest"
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
grammar org.eclipse.xtext.generator.ecore.EcoreFragmentTestLanguage with org.eclipse.xtext.common.Terminals
|
||||
|
||||
/* Suppress[external] */
|
||||
import "classpath:/org/eclipse/xtext/generator/ecore/First.ecore" as first
|
||||
generate second "http://www.eclipse.org/2009/tmf/xtext/EcoreFragmentTestLanguage" as second
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@ AType:
|
|||
AnotherType:
|
||||
'bar' {AnotherType};
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
FinderKeywords:
|
||||
'myKeyword' name=ID? 'myKeyword' 'lala';
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
FinderKeywordPairs:
|
||||
'begin' 'whatever' name=ID ('begin' nested=ID 'end')* 'end' 'begin' second=ID 'end';
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
grammar org.eclipse.xtext.generator.grammarAccess.GrammarAccessTestLanguage with org.eclipse.xtext.common.Terminals
|
||||
|
||||
/* Suppress[external] */
|
||||
import "classpath:/org/eclipse/xtext/generator/grammarAccess/ametamodel.ecore#//asubpackage" as root
|
||||
/* Suppress[external] */
|
||||
import "classpath:/org/eclipse/xtext/generator/grammarAccess/ametamodel.ecore#//asubpackage/emptyPackage/subsubpackage" as sub
|
||||
|
||||
Root returns root::AModel:
|
||||
|
|
|
@ -14,6 +14,7 @@ import "http://www.eclipse.org/emf/2002/Ecore" as ecore
|
|||
InheritedParserRule returns mm::AType:
|
||||
'element' name=ID;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
AbstractCallOverridenParserRule returns mm::AModel:
|
||||
'overridemodel' (elements+=OverridableParserRule)*;
|
||||
|
||||
|
@ -23,6 +24,7 @@ OverridableParserRule returns mm::AType :
|
|||
OverridableParserRule2 returns mm::AType :
|
||||
'other element' name=STRING;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
AbstractCallExtendedParserRule returns mm::AModel:
|
||||
'extendedmodel' (elements+=ExtendableParserRule)*;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ grammar org.eclipse.xtext.linking.Bug287988TestLanguage with org.eclipse.xtext.c
|
|||
|
||||
generate bug287988Test "http://eclipse.org/xtext/Bug287988TestLanguage"
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Model:
|
||||
('actions' attributes+=BaseAttribute*)
|
||||
| ('simple' attributes+=SimpleAttribute*)
|
||||
|
|
|
@ -12,6 +12,10 @@ generate lazyLinking "http://eclipse.org/xtext/lazyLinkingTestLanguage"
|
|||
Model :
|
||||
types+=Type*;
|
||||
|
||||
/*
|
||||
* Suppress[BidirectionalReference]
|
||||
* Suppress[potentialOverride]
|
||||
*/
|
||||
Type :
|
||||
'type' name=ID ('extends' ^extends=[Type] '.' parentId=[Property])? ('for' parentId=[Property] 'in' ^extends=[Type])? '{'
|
||||
(properties+=Property)*
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
*******************************************************************************/
|
||||
grammar org.eclipse.xtext.metamodelreferencing.tests.EcoreReferenceTestLanguage with org.eclipse.xtext.common.Terminals
|
||||
|
||||
import "http://www.eclipse.org/2011/tmf/xtext/ecorePerNsURI" // the warning is intentional
|
||||
/* Suppress[external] */
|
||||
import "http://www.eclipse.org/2011/tmf/xtext/ecorePerNsURI"
|
||||
import "http://www.eclipse.org/2011/tmf/xtext/ecorePerPlatformPlugin"
|
||||
import "http://www.eclipse.org/2011/tmf/xtext/ecorePerPlatformResource"
|
||||
import "http://www.eclipse.org/emf/2002/Ecore"
|
||||
|
|
|
@ -9,6 +9,7 @@ grammar org.eclipse.xtext.parser.antlr.Bug296889ExTestLanguage with org.eclipse.
|
|||
|
||||
generate bug296889ExTest "http://eclipse.org/xtext/Bug296889ExTestLanguage"
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Model: "Model" expressions += Expression* | "DataType" values += DataTypeExpression* ;
|
||||
|
||||
Expression: Postop | Preop ;
|
||||
|
|
|
@ -9,6 +9,7 @@ grammar org.eclipse.xtext.parser.antlr.Bug296889TestLanguage with org.eclipse.xt
|
|||
|
||||
generate bug296889Test "http://eclipse.org/xtext/Bug296889TestLanguage"
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Model: "Model" expressions += Expression* | "DataType" values += DataTypeExpression* ;
|
||||
|
||||
Expression: Postop | Preop ;
|
||||
|
|
|
@ -57,6 +57,7 @@ AbstractToken returns AbstractElement:
|
|||
Action
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
AbstractTokenWithCardinality returns AbstractElement:
|
||||
(Assignment |
|
||||
AbstractTerminal) (cardinality=('?'|'*'|'+'))?
|
||||
|
@ -120,6 +121,7 @@ TerminalGroup returns AbstractElement:
|
|||
TerminalToken ({Group.tokens+=current} (tokens+=TerminalToken)+)?
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
TerminalToken returns AbstractElement:
|
||||
TerminalTokenElement (cardinality=('?'|'*'|'+'))?
|
||||
;
|
||||
|
|
|
@ -54,6 +54,7 @@ UnorderedDatatype:
|
|||
| '14' (('a' & 'b') & ('c' & 'd'))+
|
||||
;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
UnorderedSerialization: {UnorderedSerialization} (
|
||||
'1' first?='a'? & second?='b'? & third?='c'? & forth?='d'?
|
||||
| '2' (firstAsList+='a' & secondAsList+='b')*
|
||||
|
|
|
@ -15,9 +15,11 @@ import "http://www.eclipse.org/2008/Xtext" as xtext
|
|||
Root:
|
||||
"test" (TestLinewrap | TestIndentation);
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TestLinewrap:
|
||||
"linewrap" items+=STRING*;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TestIndentation:
|
||||
"indentation" "{"
|
||||
(sub+=TestIndentation |
|
||||
|
|
|
@ -16,10 +16,12 @@ import "http://www.eclipse.org/2008/Xtext" as xtext
|
|||
|
||||
Root:
|
||||
"test" (TestLinewrap | TestIndentation);
|
||||
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TestLinewrap:
|
||||
"linewrap" items+=STRING*;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TestIndentation:
|
||||
"indentation" "{"
|
||||
(sub+=TestIndentation |
|
||||
|
|
|
@ -21,6 +21,7 @@ Term returns Expression:
|
|||
Atom:
|
||||
name=ID;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
Parens returns Expression:
|
||||
'(' Op ')' em='!'?;
|
||||
|
||||
|
@ -33,19 +34,23 @@ StrangeStuff :
|
|||
//TrickyA returns TypeA1: 'TA' TrickyA1 (name += ID)* ({TypeB.x=current} 'x' | {TypeC.x=current} 'y')? name+=STRING;
|
||||
//TrickyA1 returns TypeD: name+=ID;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TrickyB : 'TB' (name = ID type += INT)? (type += INT)*;
|
||||
|
||||
TrickyC : 'TC' name = ID ({C1.x=current} 'x')? ({C2.y=current} 'y')? ({C3.z=current} 'z')?;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TrickyD: 'TD' (name += INT foo = STRING type += ID)? (name += INT type += ID)? (type += ID)*;
|
||||
|
||||
// 34 "abc" XX 123 "de" YY x 34 DD 45 CC
|
||||
/* Suppress[noInstantiation] */
|
||||
TrickyE: 'TE' (name+=INT foo+=STRING type+=ID)* 'x' (name+=INT type+=ID)*;
|
||||
|
||||
//
|
||||
TrickyF: 'TF' (name+=ID type+=INT)* (name+=ID | type+=INT);
|
||||
|
||||
TrickyG: 'TG' tree=TrickyG1;
|
||||
TrickyG: 'TG' tree=TrickyG1;
|
||||
/* Suppress[noInstantiation] */
|
||||
TrickyG1: '[' (vals+=TrickyG2 (',' vals+=TrickyG2)*)? ']';
|
||||
TrickyG2: TrickyG1 | val=INT;
|
||||
|
||||
|
|
|
@ -23,15 +23,18 @@ EnumBug:
|
|||
|
||||
enum EnumBugEnum: array="array" | object="object" | resultSet="resultSet" | iterator="iterator";
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Commentable:
|
||||
'#3' item+=CommentableItem*;
|
||||
|
||||
CommentableItem:
|
||||
'item' id=ID;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
ValueList:
|
||||
'#4' ids+=FQN*;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
RefList:
|
||||
'#5' objs+=RefObj* 'refs' refs+=[RefObj|FQN]*;
|
||||
|
||||
|
@ -42,6 +45,7 @@ SingleRef:
|
|||
'#6' obj=RefObj 'ref' ref=[RefObj|FQN];
|
||||
|
||||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297938
|
||||
/* Suppress[noInstantiation] */
|
||||
AppendToFileEnd:
|
||||
'#7' items+=AppendToFileEndItem*;
|
||||
|
||||
|
|
|
@ -25,5 +25,6 @@ TwoRequired:
|
|||
TwoOptions:
|
||||
"twooptions" ("one" one=ID | "two" two=ID);
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Indent:
|
||||
"{" req=TwoRequired? opt=TwoOptions? indent+=Indent* "}";
|
|
@ -24,6 +24,7 @@ Term returns Expression:
|
|||
Atom:
|
||||
name=ID;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
Parens returns Expression:
|
||||
'(' Op ')' em='!'?;
|
||||
|
||||
|
@ -68,13 +69,15 @@ Loop4:
|
|||
|
||||
LoopBug285452:
|
||||
'#12' (interface?="interface"|"class") name=ID;
|
||||
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
DuplicateBug284491:
|
||||
'#13' (static?='static' | final?='final' | transient?='transient')*;
|
||||
|
||||
EmptyObjectBug284850:
|
||||
'#14' items=EmptyObjectItems;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
EmptyObjectItems:
|
||||
list+=EmptyObjectItem*;
|
||||
|
||||
|
@ -112,9 +115,11 @@ TypeBug2B: {TypeBug2B} "kb" name=ID;
|
|||
Bug305171:
|
||||
"#19" (('kx' x+=ID (',' x+=ID)*)? (('ky' y+=ID (',' y+=ID)*)? ('kz' z+=ID (',' z+=ID)*)?)) name=ID;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Bug310435Enum:
|
||||
"#20" ('kw1' lits+=EnumBug310435Lit1 | 'kw2' lits+=EnumBug310435Lit2)*;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Bug310435Val:
|
||||
"#21" ('kw1' lits+=ID | 'kw2' lits+=STRING)*;
|
||||
|
||||
|
@ -124,6 +129,7 @@ enum EnumBug310435Lit1 returns EnumBug310435Enum:
|
|||
enum EnumBug310435Lit2 returns EnumBug310435Enum:
|
||||
lit2='lit2';
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
CrossRefNameTest:
|
||||
"#22" named+=CrossRefNamed* "kw1" ("kw2" ref+=[CrossRefNamed|ID1] | "kw3" ref+=[CrossRefNamed|ID2])*;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ Model:
|
|||
domainModel = DomainModel
|
||||
;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
DomainModel:
|
||||
'entities'
|
||||
(entities+=Entity)*
|
||||
|
|
|
@ -10,6 +10,7 @@ grammar org.eclipse.xtext.testlanguages.FowlerDslTestLanguage with org.eclipse.x
|
|||
|
||||
generate fowlerdsl "http://example.xtext.org/FowlerDslTestLanguage"
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Statemachine :
|
||||
'events'
|
||||
(events+=Event)*
|
||||
|
|
|
@ -65,6 +65,7 @@ Combination1:
|
|||
Combination2:
|
||||
"#14" val1=ID (("kw1" val2=ID) | (val3+=ID val4+=ID)*);
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
Combination3:
|
||||
"#15" (val1=ID | val2=INT | val3=STRING)*;
|
||||
|
||||
|
@ -74,6 +75,7 @@ Combination4:
|
|||
List1:
|
||||
"#17" val1+=ID ("," val1+=ID)*;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
List2:
|
||||
"#18" (val1+=ID ("," val1+=ID)*)?;
|
||||
|
||||
|
@ -91,19 +93,22 @@ AltList1:
|
|||
|
||||
AltList2:
|
||||
"#23" (val1+=ID val2=ID | "kw" val1+=ID ("," val1+=ID)* val3=ID);
|
||||
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TransientObject:
|
||||
"#24" (val1=ID nested=TransientObjectSub)?;
|
||||
|
||||
TransientObjectSub:
|
||||
val2=ID val3=ID;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
TransientSerializeables1:
|
||||
"#25" (val1=ID enum1=TransientSerializeables1Enum)? (val2=ID int1=INT)?;
|
||||
|
||||
enum TransientSerializeables1Enum:
|
||||
lit1 | lit2;
|
||||
|
||||
/* Suppress[potentialOverride] */
|
||||
StaticSimplification:
|
||||
"#26" ("kw1"|{EmptyAlternativeSub}|val1=ID) ("kw2"|val2=ID) ("kw3" ("kw4" (val3=ID)+)?);
|
||||
|
||||
|
@ -117,6 +122,7 @@ TwoVersionNo2 returns TwoVersion:
|
|||
shared1=ID? shared2=ID "long" (shared3+=ID shared3+=ID*)?
|
||||
"extra" extra1=ID? ((extra2=ID extra3=ID) | "two" extra4=ID)?;
|
||||
|
||||
/* Suppress[noInstantiation] */
|
||||
Heuristic1:
|
||||
"#28" ("kw1" a+=ID b+=ID)* ("kw2" a+=ID c+=ID)* ("kw3" b+=ID c+=ID)*;
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.ParserRule;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.validation.AbstractValidationMessageAcceptingTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
*/
|
||||
public class Bug287082Test extends AbstractValidationMessageAcceptingTestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
with(XtextStandaloneSetup.class);
|
||||
}
|
||||
|
||||
@Test public void testBug285605() throws Exception {
|
||||
String grammarAsString = "grammar org.xtext.example.MyDsl with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate myDsl \"http://www.xtext.org/example/MyDsl\"\n" +
|
||||
"\n" +
|
||||
"A: {A} (feature=ID+)?;\n";
|
||||
Grammar grammar = (Grammar) getModel(grammarAsString);
|
||||
OverriddenValueInspector inspector = new OverriddenValueInspector(this);
|
||||
inspector.inspect((ParserRule) grammar.getRules().get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptWarning(String message, EObject object, EStructuralFeature feature, int index, String code,
|
||||
String... issueData) {
|
||||
if (code.equals(OverriddenValueInspector.ISSUE_CODE)) {
|
||||
String expectation = "";
|
||||
assertEquals(expectation, message);
|
||||
} else {
|
||||
super.acceptWarning(message, object, feature, index, code, issueData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -42,6 +42,14 @@ public class XtextGrammarSerializationTest extends AbstractXtextTests {
|
|||
+ "mm \"http://bar\" as fooMM\n\nStartRule returns fooMM::T:\n name=ID;";
|
||||
doTestSerialization(model, expectedModel);
|
||||
}
|
||||
|
||||
@Test public void testSerializationWithCardinalityOverride() throws Exception {
|
||||
final String model = "grammar foo with org.eclipse.xtext.common.Terminals\n"
|
||||
+ "generate mm \"http://bar\" as fooMM\n" + "StartRule returns fooMM::T: (name+=ID?)+;";
|
||||
final String expectedModel = "grammar foo with org.eclipse.xtext.common.Terminals\n\ngenerate "
|
||||
+ "mm \"http://bar\" as fooMM\n\nStartRule returns fooMM::T:\n name+=ID*;";
|
||||
doTestSerialization(model, expectedModel);
|
||||
}
|
||||
|
||||
private void doTestSerialization(String model, String expectedModel) throws Exception {
|
||||
final XtextResource resource = getResourceFromString(model);
|
||||
|
|
|
@ -12,6 +12,7 @@ import static com.google.common.collect.Maps.*;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.emf.common.util.Diagnostic;
|
||||
|
@ -44,10 +45,14 @@ import org.eclipse.xtext.UnorderedGroup;
|
|||
import org.eclipse.xtext.XtextFactory;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.util.StringInputStream;
|
||||
import org.eclipse.xtext.validation.AbstractDeclarativeValidator.State;
|
||||
import org.eclipse.xtext.validation.AbstractValidationMessageAcceptingTestCase;
|
||||
import org.eclipse.xtext.validation.AbstractValidationMessageAcceptor;
|
||||
import org.eclipse.xtext.validation.CheckMode;
|
||||
import org.eclipse.xtext.validation.IResourceValidator;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.validation.ValidationMessageAcceptor;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
@ -77,6 +82,55 @@ public class XtextValidationTest extends AbstractValidationMessageAcceptingTestC
|
|||
state.context = newHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=287082
|
||||
*/
|
||||
@Test public void testOverriddenCardinality() throws Exception {
|
||||
XtextResource resource = getResourceFromString(
|
||||
"grammar Bar with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate metamodel 'myURI'\n" +
|
||||
"Model: ((name+=ID+)+)?;\n");
|
||||
assertTrue(resource.getErrors().toString(), resource.getErrors().isEmpty());
|
||||
assertEquals(2, resource.getWarnings().size());
|
||||
|
||||
String message = resource.getWarnings().get(0).getMessage();
|
||||
assertEquals("More than one cardinality was set. Merging '+' with previously assigned cardinality to '+'.", message);
|
||||
message = resource.getWarnings().get(1).getMessage();
|
||||
assertEquals("More than one cardinality was set. Merging '?' with previously assigned cardinality to '*'.", message);
|
||||
}
|
||||
|
||||
@Test public void testSupressedWarning_01() throws Exception {
|
||||
XtextResource resource = getResourceFromString(
|
||||
"grammar org.acme.Bar with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate metamodel 'myURI'\n" +
|
||||
|
||||
"Model: child=Child;\n" +
|
||||
"/* Suppress[noInstantiation] */\n" +
|
||||
"Child: name=ID?;");
|
||||
assertTrue(resource.getErrors().toString(), resource.getErrors().isEmpty());
|
||||
assertTrue(resource.getWarnings().toString(), resource.getWarnings().isEmpty());
|
||||
|
||||
IResourceValidator validator = get(IResourceValidator.class);
|
||||
List<Issue> issues = validator.validate(resource, CheckMode.FAST_ONLY, CancelIndicator.NullImpl);
|
||||
assertTrue(issues.toString(), issues.isEmpty());
|
||||
}
|
||||
|
||||
@Test public void testSupressedWarning_02() throws Exception {
|
||||
XtextResource resource = getResourceFromString(
|
||||
"grammar org.acme.Bar with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate metamodel 'myURI'\n" +
|
||||
|
||||
"/* Suppress[potentialOverride] */\n" +
|
||||
"Parens: \n" +
|
||||
" ('(' Parens ')'|name=ID) em='!'?;");
|
||||
assertTrue(resource.getErrors().toString(), resource.getErrors().isEmpty());
|
||||
assertTrue(resource.getWarnings().toString(), resource.getWarnings().isEmpty());
|
||||
|
||||
IResourceValidator validator = get(IResourceValidator.class);
|
||||
List<Issue> issues = validator.validate(resource, CheckMode.FAST_ONLY, CancelIndicator.NullImpl);
|
||||
assertTrue(issues.toString(), issues.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=348052
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ grammar org.eclipse.xtext.xtext.ecoreInference.DataTypeRuleWithEnumResultTestLan
|
|||
with org.eclipse.xtext.enumrules.EnumRulesTestLanguage
|
||||
|
||||
import 'http://www.eclipse.org/2009/tmf/xtext/EnumRulesTest'
|
||||
/* Suppress[external] */
|
||||
import 'classpath:/org/eclipse/xtext/enumrules/enums.ecore'
|
||||
|
||||
Model:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
grammar org.eclipse.xtext.xtext.ecoreInference.Test with org.eclipse.xtext.common.Terminals
|
||||
generate root "http://root"
|
||||
/* Suppress[external] */
|
||||
import "classpath:/org/eclipse/xtext/xtext/ecoreInference/test.ecore" as test
|
||||
|
||||
Root :
|
||||
|
|
Loading…
Reference in a new issue