Skip to content

Commit

Permalink
Fixes #270 and #300 (#335)
Browse files Browse the repository at this point in the history
* Never return a NULL parsing result.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* Partial fix to #243.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* Partial fix to #243.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* Partial fix to #243 - remove commented out codes.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* Fixes #243 - Recursive model references causes error during generation

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* String literals to constants.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>

* Fixes #243. Also fixes #300. This incorporates suggestions by Alex to not make the 'generator menu' disappear but clicking it when an error is present will make it throw out an error in the console.

Signed-off-by: Erle Czar Mantos <erleczar.mantos@bosch-si.com>
  • Loading branch information
Erle Czar Mantos authored and aedelmann committed Jul 12, 2016
1 parent deec1f3 commit a597987
Show file tree
Hide file tree
Showing 14 changed files with 394 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@
*******************************************************************************/
package org.eclipse.vorto.codegen.ui.handler;

import java.util.Collection;
import java.util.Collections;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.vorto.codegen.api.IVortoCodeGenerator;
import org.eclipse.vorto.codegen.api.mapping.InvocationContext;
import org.eclipse.vorto.codegen.ui.utils.PlatformUtils;
import org.eclipse.vorto.core.api.model.informationmodel.FunctionblockProperty;
import org.eclipse.vorto.core.api.model.informationmodel.InformationModel;
import org.eclipse.vorto.core.api.model.model.Model;
import org.eclipse.vorto.core.ui.MessageDisplayFactory;
import org.eclipse.vorto.core.ui.model.IModelElement;
import org.eclipse.vorto.core.ui.model.IModelProject;
Expand All @@ -46,21 +54,29 @@ public boolean isEnabled() {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
final String generatorIdentifier = event.getParameter("org.eclipse.vorto.codegen.generator.commandParameter");
evaluate(generatorIdentifier);
PlatformUtils.switchPerspective(PlatformUtils.JAVA_PERSPECTIVE);
if (evaluate(generatorIdentifier)) {
PlatformUtils.switchPerspective(PlatformUtils.JAVA_PERSPECTIVE);
}

return null;
}

private void evaluate(String generatorName) {
private boolean evaluate(String generatorName) {

final IConfigurationElement[] configElements = getUserSelectedGenerators(generatorName);



IModelElement selectedElement = ModelProjectFactory.getInstance().getModelElementFromSelection();
if (selectedElement == null) {
MessageDisplayFactory.getMessageDisplay().displayWarning("Model was not properly selected. Please try again.");
MessageDisplayFactory.getMessageDisplay()
.displayWarning("Model was not properly selected. Please try again.");
return false;
}

if (!hasNoErrors(selectedElement)) {
MessageDisplayFactory.getMessageDisplay().displayError("Model has errors. Cannot generate.");
return false;
}

InformationModel informationModel = (InformationModel) selectedElement.getModel();

for (IConfigurationElement e : configElements) {
Expand All @@ -69,19 +85,56 @@ private void evaluate(String generatorName) {

// interested only in code generators
if (!(codeGenerator instanceof IVortoCodeGenerator)) {
continue;
continue;
}

IVortoCodeGenerator informationModelCodeGenerator = (IVortoCodeGenerator) codeGenerator;

CodeGeneratorTaskExecutor.execute(informationModel, informationModelCodeGenerator,
createInvocationContext(selectedElement.getProject(), informationModelCodeGenerator.getServiceKey()));
createInvocationContext(selectedElement.getProject(),
informationModelCodeGenerator.getServiceKey()));

} catch (Exception e1) {
MessageDisplayFactory.getMessageDisplay().displayError(e1);
throw new RuntimeException("Something went wrong during code generation", e1);
}
}

return true;
}

private boolean hasNoErrors(IModelElement selectedElement) {
return selectedElement.getDiagnostics().size() <= 0 && noLinkingErrors(selectedElement);
}

// check if model has no syntax errors
private boolean noLinkingErrors(IModelElement modelElement) {
Model model = modelElement.getModel();

if (model instanceof InformationModel) {
InformationModel infoModel = (InformationModel) model;
for (FunctionblockProperty property : infoModel.getProperties()) {
// for syntax and parsing errors
if (property.getType().eResource().getErrors().size() > 0) {
return false;
}

// for linking errors
if (getLinkingErrors(property.getType()).size() > 0) {
return false;
}
}
}
return true;
}

private Collection<Diagnostic> getLinkingErrors(EObject model) {
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(model);
switch (diagnostic.getSeverity()) {
case Diagnostic.ERROR:
return diagnostic.getChildren();
}
return Collections.emptyList();
}

private InvocationContext createInvocationContext(IModelProject project, String targetPlatform) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.eclipse.vorto.core.ui.model;

import java.util.Collection;
import java.util.Collections;

import org.eclipse.core.resources.IFile;
import org.eclipse.emf.ecore.resource.Resource;
Expand All @@ -31,15 +32,14 @@ public class DatatypeModelElement extends AbstractModelElement {

private Type model;

private Collection<Resource.Diagnostic> diagnostics;
private Collection<Resource.Diagnostic> diagnostics = Collections.emptyList();

private ModelType[] possibleReferenceTypes = new ModelType[] { ModelType.Datatype };

public DatatypeModelElement(IModelProject modelProject, IFile modelFile, IModelParser modelParser) {
super(modelProject);
this.modelFile = modelFile;
ParseModelResult<Type> parseResult = modelParser.parseModelWithError(modelFile, Type.class);
//this.model = modelParser.parseModel(modelFile, Type.class);
this.model = parseResult.getModel();
this.diagnostics = parseResult.getErrors();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package org.eclipse.vorto.editor.datatype.validation

class DatatypeSystemMessage {
public static final String ERROR_OBJ_PROPERTY_CIRCULAR_REF = 'Object property type has circular reference'
public static final String ERROR_SUPERTYPE_CIRCULAR_REF = 'Super type has circular reference'

public static final String ERROR_DUPLICATED_ENTITY_NAME = 'Entity name has been defined'
public static final String ERROR_DUPLICATED_PROPERTY_NAME = 'Property name has been defined'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,91 @@ import org.eclipse.vorto.core.api.model.datatype.Constraint
import org.eclipse.vorto.core.api.model.datatype.DatatypePackage
import org.eclipse.vorto.core.api.model.datatype.Entity
import org.eclipse.vorto.core.api.model.datatype.Enum
import org.eclipse.vorto.core.api.model.datatype.ObjectPropertyType
import org.eclipse.vorto.core.api.model.datatype.PrimitivePropertyType
import org.eclipse.vorto.core.api.model.datatype.PrimitiveType
import org.eclipse.vorto.core.api.model.datatype.Property
import org.eclipse.vorto.core.api.model.model.Model
import org.eclipse.vorto.core.api.model.model.ModelPackage
import org.eclipse.vorto.editor.datatype.internal.validation.ConstraintValueValidator
import org.eclipse.xtext.validation.Check

/**
* Custom validation rules.
*
*
* see http://www.eclipse.org/Xtext/documentation.html#validation
*/
class DatatypeValidator extends AbstractDatatypeValidator {

public val propertyValidator = new PropertyConstraintMappingValidation
public val propertyValidator = new PropertyConstraintMappingValidation

@Check
def checkCircularRefInObjectPropertyType(ObjectPropertyType ref) {
if (ref.type != null) {
try {
val parent = ValidatorUtils.getParentOfType(ref, Model) as Model;
if (parent != null) {
if (ValidatorUtils.hasCircularReference(parent as Model, ref.type, ValidatorUtils.entityTypeToChildrenSupplierFunction)) {
error(DatatypeSystemMessage.ERROR_OBJ_PROPERTY_CIRCULAR_REF, ref, DatatypePackage.Literals.OBJECT_PROPERTY_TYPE__TYPE);
}
}
} catch(Exception e) {
e.printStackTrace
}
}
}

@Check
def checkCircularRefInSuperType(Entity entity) {
if (entity.superType != null) {
try {
if (ValidatorUtils.hasCircularReference(entity, entity.superType, ValidatorUtils.entityTypeToChildrenSupplierFunction)) {
error(DatatypeSystemMessage.ERROR_SUPERTYPE_CIRCULAR_REF, entity, DatatypePackage.Literals.ENTITY__SUPER_TYPE);
}
} catch(Exception e) {
e.printStackTrace
}
}
}

@Check
def checkConstraint(Property prop) {
var constraints = prop.constraintRule.constraints

if(constraints.length == 0) return;
var primi = prop.type as PrimitivePropertyType
var primi = prop.type as PrimitivePropertyType
var isMultiplcity = prop.multiplicity;
for (constraint : constraints) {
verifyConstraintForType(primi, constraint, isMultiplcity)
}
}

def verifyConstraintForType(PrimitivePropertyType primitivePropertyType, Constraint constraint, boolean isMultiplcity) {

def verifyConstraintForType(PrimitivePropertyType primitivePropertyType, Constraint constraint,
boolean isMultiplcity) {
if (!isValidConstraintType(primitivePropertyType.type, constraint)) {
error(propertyValidator.errorMessage, constraint, DatatypePackage.Literals.CONSTRAINT__TYPE)
}else{
var validator = ConstraintValidatorFactory.getValueValidator(constraint.type)
error(propertyValidator.errorMessage, constraint, DatatypePackage.Literals.CONSTRAINT__TYPE)
} else {
var validator = ConstraintValidatorFactory.getValueValidator(constraint.type)
if (!isValidConstraintValue(validator, primitivePropertyType.type, constraint)) {
error(validator.errorMessage, constraint, DatatypePackage.Literals.CONSTRAINT__CONSTRAINT_VALUES)
}
}

if(isMimeConstraint(primitivePropertyType.type.getName(), constraint)){
if(!isMultiplcity)
error(DatatypeSystemMessage.ERROR_MIMETYPE_FOR_BYTE, constraint, DatatypePackage.Literals.CONSTRAINT__TYPE)
}
error(validator.errorMessage, constraint, DatatypePackage.Literals.CONSTRAINT__CONSTRAINT_VALUES)
}


}

if (isMimeConstraint(primitivePropertyType.type.getName(), constraint)) {
if (!isMultiplcity)
error(DatatypeSystemMessage.ERROR_MIMETYPE_FOR_BYTE, constraint,
DatatypePackage.Literals.CONSTRAINT__TYPE)
}
}

def isValidConstraintType(PrimitiveType primitiveType, Constraint constraint) {
return propertyValidator.checkPropertyConstraints(primitiveType, constraint)
}

def isValidConstraintValue(ConstraintValueValidator validator, PrimitiveType primitiveType, Constraint constraint) {
return validator.evaluateValueType(primitiveType, constraint)
}

def isMimeConstraint(String primitiveTypeName, Constraint constraint) {
return "MIMETYPE" == constraint.type.literal && "byte" == primitiveTypeName
}
Expand All @@ -85,14 +117,15 @@ public val propertyValidator = new PropertyConstraintMappingValidation
error(DatatypeSystemMessage.ERROR_ENUMNAME_INVALID_CAMELCASE, ent, ModelPackage.Literals.MODEL__NAME)
}
}

@Check
def checkDuplicatedLiteral(Enum enu){
def checkDuplicatedLiteral(Enum enu) {
var list = enu.enums
var set = new HashSet<String>();
for (var i = 0; i < list.length; i++) {
if(!set.add(list.get(i).name)){
error(DatatypeSystemMessage.ERROR_DUPLICATED_ENUM_LITERAL, list.get(i), DatatypePackage.Literals.ENUM_LITERAL__NAME)
if (!set.add(list.get(i).name)) {
error(DatatypeSystemMessage.ERROR_DUPLICATED_ENUM_LITERAL, list.get(i),
DatatypePackage.Literals.ENUM_LITERAL__NAME)
}
}
}
Expand All @@ -101,7 +134,7 @@ public val propertyValidator = new PropertyConstraintMappingValidation
def checkDuplicatedConstraint(Property feature) {
var set = new HashSet<String>();
var list = feature.constraintRule.constraints;
for (var i = 0; i < list.length; i ++) {
for (var i = 0; i < list.length; i++) {
var con = list.get(i);
if (!set.add(con.type.literal)) {
error(DatatypeSystemMessage.ERROR_DUPLICATED_CONSTRAINT, con, DatatypePackage.Literals.CONSTRAINT__TYPE)
Expand All @@ -120,15 +153,22 @@ public val propertyValidator = new PropertyConstraintMappingValidation
def boolean isCamelCasedName(String name) {
!Character.isUpperCase((name).charAt(0))
}


def checkDuplicatedProperty(List<Property> props){
def checkDuplicatedProperty(List<Property> props) {
var set = new HashSet<String>();
for ( pp : props){
if(!set.add(pp.name)){

for (pp : props) {
if (!set.add(pp.name)) {
error(DatatypeSystemMessage.ERROR_DUPLICATED_PROPERTY_NAME, pp, DatatypePackage.Literals.PROPERTY__NAME)
}
}
}

@Check
def checkPropertyName(Property property) {
var name = property.name
if (name.endsWith('TS')) {
error(DatatypeSystemMessage.ERROR_PROPNAME_SUFFIX_TS, property, DatatypePackage.Literals.PROPERTY__NAME)
}
}
}
Loading

0 comments on commit a597987

Please sign in to comment.