[505805] Missing validation message on sequence calls
Bug: 505805
Change-Id: I7adeafe71adce3f1a9925f15563aa47244740adc
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/ServicesValidationResult.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/ServicesValidationResult.java
index 07799f4..c32ad25 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/ServicesValidationResult.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/ServicesValidationResult.java
@@ -33,6 +33,11 @@
public class ServicesValidationResult {
/**
+ * The current line separator which will be used by the tooling in order to compute the description.
+ */
+ private static final String LS = System.getProperty("line.separator");
+
+ /**
* The {@link IReadOnlyQueryEnvironment}.
*/
private final IReadOnlyQueryEnvironment queryEnvironment;
@@ -122,14 +127,12 @@
for (Set<IType> resultTypes : map.values()) {
Set<IType> flattenedTypes = new LinkedHashSet<IType>();
for (IType resultType : resultTypes) {
- if (!(resultType instanceof NothingType)) {
- // flatten
- if (resultType instanceof ICollectionType) {
- flattenedTypes.add(new SetType(queryEnvironment, ((ICollectionType)resultType)
- .getCollectionType()));
- } else {
- flattenedTypes.add(new SetType(queryEnvironment, resultType));
- }
+ // flatten
+ if (resultType instanceof ICollectionType) {
+ flattenedTypes.add(new SetType(queryEnvironment, ((ICollectionType)resultType)
+ .getCollectionType()));
+ } else {
+ flattenedTypes.add(new SetType(queryEnvironment, resultType));
}
}
resultTypes.clear();
@@ -146,14 +149,12 @@
for (Set<IType> resultTypes : map.values()) {
Set<IType> flattenedTypes = new LinkedHashSet<IType>();
for (IType resultType : resultTypes) {
- if (!(resultType instanceof NothingType)) {
- // flatten
- if (resultType instanceof ICollectionType) {
- flattenedTypes.add(new SequenceType(queryEnvironment,
- ((ICollectionType)resultType).getCollectionType()));
- } else {
- flattenedTypes.add(new SequenceType(queryEnvironment, resultType));
- }
+ // flatten
+ if (resultType instanceof ICollectionType) {
+ flattenedTypes.add(new SequenceType(queryEnvironment, ((ICollectionType)resultType)
+ .getCollectionType()));
+ } else {
+ flattenedTypes.add(new SequenceType(queryEnvironment, resultType));
}
}
resultTypes.clear();
@@ -170,16 +171,57 @@
public Set<IType> getResultingTypes() {
final Set<IType> result = new LinkedHashSet<IType>();
+ final Set<IType> aggregated = new LinkedHashSet<IType>();
if (!typesPerService.isEmpty()) {
for (Entry<IService, Map<List<IType>, Set<IType>>> entry : typesPerService.entrySet()) {
final IService service = entry.getKey();
final Map<List<IType>, Set<IType>> types = entry.getValue();
Set<IType> validatedTypes = service.validateAllType(validationServices, queryEnvironment,
types);
- result.addAll(validatedTypes);
+ aggregated.addAll(validatedTypes);
}
} else {
- result.addAll(serviceNotFoundMessages.values());
+ aggregated.addAll(serviceNotFoundMessages.values());
+ }
+
+ final StringBuilder builderSequenceNothing = new StringBuilder();
+ final StringBuilder builderSetNothing = new StringBuilder();
+ final StringBuilder builderNothing = new StringBuilder();
+ for (IType type : aggregated) {
+ if (type instanceof ICollectionType) {
+ if (((ICollectionType)type).getCollectionType() instanceof NothingType) {
+ final NothingType collectionType = (NothingType)((ICollectionType)type)
+ .getCollectionType();
+ if (type instanceof SequenceType) {
+ builderSequenceNothing.append(collectionType.getMessage());
+ builderSequenceNothing.append(LS);
+ } else if (type instanceof SetType) {
+ builderSetNothing.append(collectionType.getMessage());
+ builderSetNothing.append(LS);
+ } else {
+ throw new IllegalStateException("new collection type ?");
+ }
+ } else {
+ result.add(type);
+ }
+ } else if (type instanceof NothingType) {
+ builderNothing.append(((NothingType)type).getMessage());
+ builderNothing.append(LS);
+ } else {
+ result.add(type);
+ }
+ }
+
+ if (builderSequenceNothing.length() != 0) {
+ result.add(new SequenceType(queryEnvironment, new NothingType(builderSequenceNothing.substring(0,
+ builderSequenceNothing.length() - 1))));
+ }
+ if (builderSetNothing.length() != 0) {
+ result.add(new SetType(queryEnvironment, new NothingType(builderSetNothing.substring(0,
+ builderSetNothing.length() - 1))));
+ }
+ if (builderNothing.length() != 0) {
+ result.add(new NothingType(builderNothing.substring(0, builderNothing.length() - 1)));
}
return result;
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/services/AnyServices.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/services/AnyServices.java
index 5a1ea08..35467a9 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/services/AnyServices.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/services/AnyServices.java
@@ -18,6 +18,8 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.acceleo.annotations.api.documentation.Documentation;
@@ -35,7 +37,11 @@
import org.eclipse.acceleo.query.runtime.impl.ValidationServices;
import org.eclipse.acceleo.query.validation.type.ClassType;
import org.eclipse.acceleo.query.validation.type.EClassifierType;
+import org.eclipse.acceleo.query.validation.type.ICollectionType;
import org.eclipse.acceleo.query.validation.type.IType;
+import org.eclipse.acceleo.query.validation.type.NothingType;
+import org.eclipse.acceleo.query.validation.type.SequenceType;
+import org.eclipse.acceleo.query.validation.type.SetType;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
@@ -399,6 +405,7 @@
}
private static class OCLAsTypeService extends FilterService {
+
public OCLAsTypeService(Method publicMethod, Object serviceInstance) {
super(publicMethod, serviceInstance);
}
@@ -422,17 +429,58 @@
result.add(services.nothing("Unknown type %s", "null"));
}
} else {
- if (receiverType instanceof EClassifierType && !environment.getEPackageProvider()
- .isRegistered(((EClassifierType)receiverType).getType())) {
+ if (receiverType instanceof EClassifierType
+ && !environment.getEPackageProvider().isRegistered(
+ ((EClassifierType)receiverType).getType())) {
result.add(services.nothing("%s is not registered within the current environment.",
receiverType));
- } else if (filterType instanceof EClassifierType && !environment.getEPackageProvider()
- .isRegistered(((EClassifierType)filterType).getType())) {
+ } else if (filterType instanceof EClassifierType
+ && !environment.getEPackageProvider().isRegistered(
+ ((EClassifierType)filterType).getType())) {
result.add(services.nothing("%s is not registered within the current environment.",
filterType));
} else {
- result.add(services.nothing("%s is not compatible with type %s", receiverType,
- filterType));
+ result.add(services
+ .nothing("%s is not compatible with type %s", receiverType, filterType));
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public Set<IType> validateAllType(ValidationServices services,
+ IReadOnlyQueryEnvironment queryEnvironment, Map<List<IType>, Set<IType>> allTypes) {
+ final Set<IType> result = new LinkedHashSet<IType>();
+ final StringBuilder builder = new StringBuilder();
+
+ for (Entry<List<IType>, Set<IType>> entry : allTypes.entrySet()) {
+ for (IType possibleType : entry.getValue()) {
+ final IType rawType;
+ if (possibleType instanceof ICollectionType) {
+ rawType = ((ICollectionType)possibleType).getCollectionType();
+ } else {
+ rawType = possibleType;
+ }
+ if (rawType instanceof NothingType) {
+ builder.append("\n");
+ builder.append(((NothingType)rawType).getMessage());
+ } else {
+ result.add(possibleType);
+ }
+ }
+ }
+
+ if (result.isEmpty()) {
+ final IType resultType = allTypes.entrySet().iterator().next().getValue().iterator().next();
+ final NothingType nothing = services.nothing("Nothing will be left after calling %s:"
+ + builder.toString(), getName());
+ if (resultType instanceof SequenceType) {
+ result.add(new SequenceType(queryEnvironment, nothing));
+ } else if (resultType instanceof SetType) {
+ result.add(new SetType(queryEnvironment, nothing));
+ } else {
+ result.add(nothing);
}
}
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
index 9ea70f9..7418577 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
@@ -186,6 +186,214 @@
}
@Test
+ public void flattenSequenceNothingFeatureNotExistingAccessTest() {
+ final IValidationResult validationResult = engine.validate("self->asSequence().notExisting",
+ variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof NothingType);
+ assertEquals("Feature notExisting not found in EClass EClass", ((NothingType)((SequenceType)type)
+ .getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(validationResult.getMessages().get(0), ValidationMessageLevel.INFO,
+ "Empty collection: Feature notExisting not found in EClass EClass", 18, 30);
+ }
+
+ @Test
+ public void flattenSetNothingFeatureNotExistingAccessTest() {
+ final IValidationResult validationResult = engine
+ .validate("self->asSet().notExisting", variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SetType);
+ assertTrue(((SetType)type).getCollectionType() instanceof NothingType);
+ assertEquals("Feature notExisting not found in EClass EClass", ((NothingType)((SetType)type)
+ .getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(validationResult.getMessages().get(0), ValidationMessageLevel.INFO,
+ "Empty collection: Feature notExisting not found in EClass EClass", 13, 25);
+ }
+
+ @Test
+ public void flattenSequenceNothingOclAsTypeTest() {
+ final IValidationResult validationResult = engine.validate(
+ "self->asSequence().oclAsType(ecore::EPackage)", variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof NothingType);
+ assertEquals(
+ "Nothing will be left after calling oclAsType:\nEClassifier=EClass is not compatible with type EClassifierLiteral=EPackage",
+ ((NothingType)((SequenceType)type).getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.INFO,
+ "Empty collection: Nothing will be left after calling oclAsType:\nEClassifier=EClass is not compatible with type EClassifierLiteral=EPackage",
+ 18, 45);
+ }
+
+ @Test
+ public void flattenSetNothingOclAsTypeTest() {
+ final IValidationResult validationResult = engine.validate(
+ "self->asSequence().oclAsType(ecore::EPackage)", variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof NothingType);
+ assertEquals(
+ "Nothing will be left after calling oclAsType:\nEClassifier=EClass is not compatible with type EClassifierLiteral=EPackage",
+ ((NothingType)((SequenceType)type).getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.INFO,
+ "Empty collection: Nothing will be left after calling oclAsType:\nEClassifier=EClass is not compatible with type EClassifierLiteral=EPackage",
+ 18, 45);
+ }
+
+ @Test
+ public void flattenSequenceNothingMultipleTypesNotExistingOnAnyAccessTest() {
+ final Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEClass()));
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
+ variableTypes.put("multiType", selfTypes);
+
+ final IValidationResult validationResult = engine.validate("multiType->asSequence().notExisting",
+ variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof NothingType);
+ assertEquals(
+ "Feature notExisting not found in EClass EClass\nFeature notExisting not found in EClass EPackage",
+ ((NothingType)((SequenceType)type).getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.INFO,
+ "Empty collection: Feature notExisting not found in EClass EClass\nFeature notExisting not found in EClass EPackage",
+ 23, 35);
+ }
+
+ @Test
+ public void flattenSetNothingMultipleTypesNotExistingOnAnyAccessTest() {
+ final Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEClass()));
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
+ variableTypes.put("multiType", selfTypes);
+
+ final IValidationResult validationResult = engine.validate("multiType->asSet().notExisting",
+ variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(1, possibleTypes.size());
+ final IType type = possibleTypes.iterator().next();
+ assertTrue(type instanceof SetType);
+ assertTrue(((SetType)type).getCollectionType() instanceof NothingType);
+ assertEquals(
+ "Feature notExisting not found in EClass EClass\nFeature notExisting not found in EClass EPackage",
+ ((NothingType)((SetType)type).getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.INFO,
+ "Empty collection: Feature notExisting not found in EClass EClass\nFeature notExisting not found in EClass EPackage",
+ 18, 30);
+ }
+
+ @Test
+ public void flattenSequenceNothingMultipleTypesNotExistingOnOneAccessTest() {
+ final Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEClass()));
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
+ variableTypes.put("multiType", selfTypes);
+
+ final IValidationResult validationResult = engine.validate("multiType->asSequence().eClassifiers",
+ variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(2, possibleTypes.size());
+ final Iterator<IType> it = possibleTypes.iterator();
+ IType type = it.next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof EClassifierType);
+ assertEquals(EcorePackage.eINSTANCE.getEClassifier(), ((EClassifierType)((SequenceType)type)
+ .getCollectionType()).getType());
+ type = it.next();
+ assertTrue(type instanceof SequenceType);
+ assertTrue(((SequenceType)type).getCollectionType() instanceof NothingType);
+ assertEquals("Feature eClassifiers not found in EClass EClass", ((NothingType)((SequenceType)type)
+ .getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(validationResult.getMessages().get(0), ValidationMessageLevel.INFO,
+ "Empty collection: Feature eClassifiers not found in EClass EClass", 23, 36);
+ }
+
+ @Test
+ public void flattenSetNothingMultipleTypesNotExistingOnOneAccessTest() {
+ final Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEClass()));
+ selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
+ variableTypes.put("multiType", selfTypes);
+
+ final IValidationResult validationResult = engine.validate("multiType->asSet().eClassifiers",
+ variableTypes);
+ final Expression ast = validationResult.getAstResult().getAst();
+
+ Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+ assertEquals(0, stripNothingTypes(possibleTypes).size());
+ assertEquals(2, possibleTypes.size());
+ final Iterator<IType> it = possibleTypes.iterator();
+ IType type = it.next();
+ assertTrue(type instanceof SetType);
+ assertTrue(((SetType)type).getCollectionType() instanceof EClassifierType);
+ assertEquals(EcorePackage.eINSTANCE.getEClassifier(), ((EClassifierType)((SetType)type)
+ .getCollectionType()).getType());
+ type = it.next();
+ assertTrue(type instanceof SetType);
+ assertTrue(((SetType)type).getCollectionType() instanceof NothingType);
+ assertEquals("Feature eClassifiers not found in EClass EClass", ((NothingType)((SetType)type)
+ .getCollectionType()).getMessage());
+
+ assertEquals(1, validationResult.getMessages().size());
+ assertValidationMessage(validationResult.getMessages().get(0), ValidationMessageLevel.INFO,
+ "Empty collection: Feature eClassifiers not found in EClass EClass", 18, 31);
+ }
+
+ @Test
public void intliteralTest() {
final IValidationResult validationResult = engine.validate("2", variableTypes);
final Expression ast = validationResult.getAstResult().getAst();