Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import nl.esi.xtext.actions.actions.PCFragment
import nl.esi.xtext.actions.actions.PCFragmentDefinition
import nl.esi.xtext.actions.actions.PCFragmentReference
import nl.esi.xtext.actions.actions.RecordFieldAssignmentAction
import nl.esi.xtext.expressions.expression.Expression
import nl.esi.xtext.expressions.expression.ExpressionRecordAccess
import nl.esi.xtext.expressions.expression.ExpressionVariable

Expand Down Expand Up @@ -57,12 +58,26 @@ class ActionsUtilities {
}

def static getFields(RecordFieldAssignmentAction action) {
return action.fieldAccess.fields
}

def static getField(RecordFieldAssignmentAction action) {
return action.fieldAccess.field
}

def static getFields(Expression expression) {
val fields = newLinkedList()
var record = action.fieldAccess
var record = expression
while (record instanceof ExpressionRecordAccess) {
fields.addFirst(record.field)
record = record.record
}
return fields
}

def static getField(Expression expression) {
if (expression instanceof ExpressionRecordAccess) {
return expression.field
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.eclipse.xtext.serializer.impl.Serializer;
import org.eclipse.xtext.util.ITextRegion;

import com.google.common.base.Strings;
import com.google.inject.Guice;
import com.google.inject.Module;

Expand Down Expand Up @@ -296,18 +297,32 @@ public static final class ValidationException extends Exception {
private static final long serialVersionUID = 4543121779695994392L;

public ValidationException(Diagnostic diagnostic) {
super(createMessage(diagnostic), new DiagnosticException(diagnostic));
super(createMessage(diagnostic, ""), new DiagnosticException(diagnostic));
}

@Override
public synchronized DiagnosticException getCause() {
return DiagnosticException.class.cast(super.getCause());
}

private static String createMessage(Diagnostic diagnostic) {
private static String createMessage(Diagnostic diagnostic, String indent) {
StringBuilder message = new StringBuilder(indent);
message.append(switch (diagnostic.getSeverity()) {
case Diagnostic.INFO -> "INFO: ";
case Diagnostic.WARNING -> "WARNING: ";
case Diagnostic.ERROR -> "ERROR: ";
default -> "";
});
message.append(diagnostic.getMessage());

String cIndent = Strings.isNullOrEmpty(indent) ? "- " : " " + indent;
String details = diagnostic.getChildren().stream().filter(c -> c.getSeverity() != Diagnostic.OK)
.map(c -> "- " + c.getMessage()).collect(Collectors.joining("\n"));
return diagnostic.getMessage() + (details.isEmpty() ? "" : "\n" + details);
.map(c -> createMessage(c, cIndent)).collect(Collectors.joining("\n"));
if (!details.isEmpty()) {
message.append("\n").append(details);
}

return message.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,8 @@ class BaseValidator extends AbstractBaseValidator {
}
}
}

protected static def <T> Iterable<T> getDuplicatesBy(Iterable<T> source, (T)=>Object functor) {
return source.groupBy(functor).values.filter[size > 1].flatten
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class ExpressionIdeProposalProvider extends AbstractExpressionIdeProposalProvide
}

try {
val defaultValue = ProposalHelper.defaultValue(typeAnn, targetName)
val defaultValue = createDefaultValueEntry(typeAnn, targetName, context)
val proposal = proposalCreator.createProposal(defaultValue, context, [ entry |
entry.kind = ContentAssistEntry.KIND_SNIPPET
entry.label = ProposalHelper.getTypeName(typeAnn)
Expand All @@ -103,14 +103,18 @@ class ExpressionIdeProposalProvider extends AbstractExpressionIdeProposalProvide
}
}

protected def String createDefaultValueEntry(TypeAnnotation typeAnn, String targetName, ContentAssistContext context) {
return ProposalHelper.defaultValue(typeAnn, targetName)
}

protected def createDefaultValue(Type type, String targetName, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
if (type instanceof TypeReference && type.type instanceof EnumTypeDecl) {
createEnumValues(type.type as EnumTypeDecl, context, acceptor)
return;
}

try {
val defaultValue = ProposalHelper.defaultValue(type, targetName)
val defaultValue = createDefaultValueEntry(type, targetName, context)
val proposal = proposalCreator.createProposal(defaultValue, context, [ entry |
entry.kind = ContentAssistEntry.KIND_SNIPPET
entry.label = ProposalHelper.getTypeName(type)
Expand All @@ -125,6 +129,10 @@ class ExpressionIdeProposalProvider extends AbstractExpressionIdeProposalProvide
}
}

protected def String createDefaultValueEntry(Type type, String targetName, ContentAssistContext context) {
return ProposalHelper.defaultValue(type, targetName)
}

protected def createEnumValues(EnumTypeDecl type, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
for (literal : type.literals) {
val value = '''«type.name»::«literal.name»'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@

import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.util.EcoreUtil;

import com.google.common.base.Predicates;

import nl.esi.xtext.expressions.expression.Expression;
import nl.esi.xtext.expressions.expression.ExpressionAddition;
import nl.esi.xtext.expressions.expression.ExpressionAnd;
Expand Down Expand Up @@ -56,7 +59,6 @@
import nl.esi.xtext.types.types.MapTypeConstructor;
import nl.esi.xtext.types.types.MapTypeDecl;
import nl.esi.xtext.types.types.RecordField;
import nl.esi.xtext.types.types.RecordFieldKind;
import nl.esi.xtext.types.types.RecordTypeDecl;
import nl.esi.xtext.types.types.SimpleTypeDecl;
import nl.esi.xtext.types.types.Type;
Expand Down Expand Up @@ -84,16 +86,24 @@ public static String getTypeName(TypeAnnotation typeAnn) {
}

public static String defaultValue(TypeAnnotation typeAnn, String targetName) throws UnsupportedTypeException {
return createDefaultValueEntry(typeAnn.getType(), targetName, "");
return createDefaultValueEntry(typeAnn.getType(), targetName, "", Predicates.alwaysTrue());
}

public static String defaultValue(TypeAnnotation typeAnn, String targetName, Predicate<? super RecordField> filter) throws UnsupportedTypeException {
return createDefaultValueEntry(typeAnn.getType(), targetName, "", filter);
}

public static String defaultValue(Type type, String targetName) throws UnsupportedTypeException {
return createDefaultValue(type, targetName, "");
return createDefaultValue(type, targetName, "", Predicates.alwaysTrue());
}

public static String defaultValue(Type type, String targetName, Predicate<? super RecordField> filter) throws UnsupportedTypeException {
return createDefaultValue(type, targetName, "", filter);
}

private static String createDefaultValue(Type type, String targetName, String indent) throws UnsupportedTypeException {
private static String createDefaultValue(Type type, String targetName, String indent, Predicate<? super RecordField> filter) throws UnsupportedTypeException {
if (type instanceof TypeReference) {
return createDefaultValueEntry(type, targetName, indent);
return createDefaultValueEntry(type, targetName, indent, filter);
} else if (type instanceof VectorTypeConstructor) {
return "<" + getTypeName(type) + ">[]";
} else if (type instanceof MapTypeConstructor) {
Expand All @@ -102,17 +112,17 @@ private static String createDefaultValue(Type type, String targetName, String in
throw new UnsupportedTypeException(type);
}

private static String createDefaultValueEntry(Type type, String targetName, String indent) throws UnsupportedTypeException {
private static String createDefaultValueEntry(Type type, String targetName, String indent, Predicate<? super RecordField> filter) throws UnsupportedTypeException {
if (type instanceof TypeReference) {
return createDefaultValue(type.getType(), targetName, indent);
return createDefaultValue(type.getType(), targetName, indent, filter);
} else if (type instanceof VectorTypeConstructor vecType) {
if (vecType.getDimensions().size() > 1) {
return createDefaultValue(getOuterDimension(vecType), null, indent);
return createDefaultValue(getOuterDimension(vecType), null, indent, filter);
}
return createDefaultValue(type.getType(), targetName, indent);
return createDefaultValue(type.getType(), targetName, indent, filter);
} else if (type instanceof MapTypeConstructor mapType) {
String key = createDefaultValue(type.getType(), null, indent);
String value = createDefaultValue(mapType.getValueType(), null, indent);
String key = createDefaultValue(type.getType(), null, indent, filter);
String value = createDefaultValue(mapType.getValueType(), null, indent, filter);
return key + " -> " + value;
}
throw new UnsupportedTypeException(type);
Expand All @@ -124,9 +134,9 @@ private static Type getOuterDimension(VectorTypeConstructor vectorType) {
return outerDimension;
}

private static String createDefaultValue(TypeDecl type, String targetName, String indent) throws UnsupportedTypeException {
private static String createDefaultValue(TypeDecl type, String targetName, String indent, Predicate<? super RecordField> filter) throws UnsupportedTypeException {
if (type instanceof SimpleTypeDecl simpleType) {
if (simpleType.getBase() != null) return createDefaultValue(simpleType.getBase(), targetName, indent);
if (simpleType.getBase() != null) return createDefaultValue(simpleType.getBase(), targetName, indent, filter);
else if (simpleType.getName().equals("int")) return "0";
else if (simpleType.getName().equals("real")) return "0.0";
else if (simpleType.getName().equals("bool")) return "true";
Expand All @@ -139,16 +149,16 @@ private static String createDefaultValue(TypeDecl type, String targetName, Strin
} else if (type instanceof MapTypeDecl) {
return "{}";
} else if (type instanceof RecordTypeDecl recType) {
List<RecordField> recFields = getAllFields(recType).stream().filter(f -> !RecordFieldKind.SYMBOLIC.equals(f.getKind())).toList();
List<RecordField> recFields = getAllFields(recType).stream().filter(filter).toList();
if (recFields.size() > 1) {
String fieldIndent = indent + "\t";
String value = recFields.stream()
.map(f -> String.format("%s%s = %s", fieldIndent, f.getName(), createDefaultValue(f.getType(), f.getName(), fieldIndent)))
.map(f -> String.format("%s%s = %s", fieldIndent, f.getName(), createDefaultValue(f.getType(), f.getName(), fieldIndent, filter)))
.collect(Collectors.joining(",\n"));
return String.format("%s {\n%s\n%s}", type.getName(), value, indent);
} else {
String value = recFields.stream()
.map(f -> String.format("%s = %s", f.getName(), createDefaultValue(f.getType(), f.getName(), indent)))
.map(f -> String.format("%s = %s", f.getName(), createDefaultValue(f.getType(), f.getName(), indent, filter)))
.collect(Collectors.joining(",\n"));
return String.format("%s { %s }", type.getName(), value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ package nl.esi.xtext.types.validation

import com.google.inject.Inject
import java.util.Set
import nl.esi.xtext.common.lang.base.BasePackage
import nl.esi.xtext.common.lang.base.ModelContainer
import nl.esi.xtext.types.BasicTypes
import nl.esi.xtext.types.scoping.TypesImportUriGlobalScopeProvider
import nl.esi.xtext.types.types.EnumTypeDecl
import nl.esi.xtext.types.types.GenericsTypeParam
import nl.esi.xtext.types.types.MapTypeConstructor
import nl.esi.xtext.types.types.RecordFieldKind
import nl.esi.xtext.types.types.RecordTypeDecl
import nl.esi.xtext.types.types.SimpleTypeDecl
import nl.esi.xtext.types.types.Type
import nl.esi.xtext.types.types.TypesModel
import nl.esi.xtext.types.types.TypesPackage
import nl.esi.xtext.common.lang.base.BasePackage
import nl.esi.xtext.common.lang.base.ModelContainer
import org.eclipse.core.runtime.Platform
import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EValidator
Expand All @@ -34,7 +34,6 @@ import org.eclipse.xtext.validation.Check
import org.eclipse.xtext.validation.EValidatorRegistrar

import static extension nl.esi.xtext.types.utilities.TypeUtilities.*
import nl.esi.xtext.types.types.GenericsTypeParam

/**
* This class contains custom validation rules.
Expand Down Expand Up @@ -240,19 +239,19 @@ class TypesValidator extends AbstractTypesValidator {
* + the chain of dependencies induced by record fields contains no cycles.
* Clarification: record R1 with field A of type R2, R2 with field b of type R1 is not allowed.
* Fields of vector types with base another record type should also be considered.
* In XPlus, records are treated as values. The structure mentioned above can never be created.
* In ComMA, records are treated as values. The structure mentioned above can never be created.
*/

/*
* This methods implements the mechanism for registering third-party extensions to the
* validators of the XPlus languages.
* validators of the ComMA languages.
* All languages that directly or indirectly extend Types language inherit it.
*/

@Inject
override register(EValidatorRegistrar registrar) {
super.register(registrar)
val VALIDATOR_ID = "nl.esi.xtext.types.xplusValidator"
val VALIDATOR_ID = "nl.esi.xtext.types.commaValidator"
val reg = Platform.getExtensionRegistry()
if(reg !== null){
val extensions = reg.getConfigurationElementsFor(VALIDATOR_ID)
Expand All @@ -266,15 +265,4 @@ class TypesValidator extends AbstractTypesValidator {
}
}
}

/**
* All fields of a record cannot be marked symbolic.
*/
@Check
def checkSymbolicField(RecordTypeDecl type) {
val allField = type.allFields
if (allField.forall[kind != RecordFieldKind::CONCRETE]) {
error('''At least 1 field must be concrete for record «type.name»''', TypesPackage.Literals.RECORD_TYPE_DECL__FIELDS)
}
}
}
Loading