import org.simantics.scl.compiler.internal.parsing.translation.RelationRepository;
import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
import org.simantics.scl.compiler.module.ImportDeclaration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import gnu.trove.map.hash.THashMap;
public class DeclarationClassification {
- private static final Logger LOGGER = LoggerFactory.getLogger(DeclarationClassification.class);
-
ArrayList<ImportDeclaration> importsAst = new ArrayList<ImportDeclaration>();
ArrayList<DDataAst> dataTypesAst = new ArrayList<DDataAst>();
ArrayList<DTypeAst> typeAliasesAst = new ArrayList<DTypeAst>();
currentAnnotations = new ArrayList<DAnnotationAst>(2);
}
if(declaration.name.name.equals("Eq") || declaration.name.name.equals("Hashable")) {
- LOGGER.warn("Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
+ errorLog.logWarning(declaration.location, "Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
return;
}
instancesAst.add(new ProcessedDInstanceAst(
currentAnnotations = new ArrayList<DAnnotationAst>(2);
}
if(declaration.name.name.equals("Eq") || declaration.name.name.equals("Hashable")) {
- LOGGER.warn("Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
+ errorLog.logWarning(declaration.location, "Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
return;
}
derivingInstancesAst.add(declaration);
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.annotations.AnnotationUtils;
import org.simantics.scl.compiler.elaboration.fundeps.Fundep;
import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
import org.simantics.scl.compiler.elaboration.macros.StandardMacroRule;
+import org.simantics.scl.compiler.elaboration.modules.DeprecatedProperty;
import org.simantics.scl.compiler.elaboration.modules.InlineProperty;
import org.simantics.scl.compiler.elaboration.modules.MethodImplementation;
import org.simantics.scl.compiler.elaboration.modules.PrivateProperty;
}
}.findComponents();
- if(errorLog.isEmpty()) {
+ if(errorLog.hasNoErrors()) {
for(DTypeAst typeAlias : orderedTypeAliases) {
TypeAlias alias = (TypeAlias)module.getTypeDescriptor(typeAlias.name);
TypeTranslationContext context = createTypeTranslationContext();
value.addProperty(PrivateProperty.INSTANCE);
}
else if(annotation.id.text.equals("@deprecated")) {
- // TODO
+ String description = "";
+ if(annotation.parameters.length > 0) {
+ if(annotation.parameters.length > 1)
+ errorLog.log(annotation.location, "Invalid number of parameters, expected one string.");
+ else {
+ String temp = AnnotationUtils.extractString(annotation.parameters[0]);
+ if(temp == null)
+ errorLog.log(annotation.location, "Invalid parameter, expected one string.");
+ else
+ description = temp;
+ }
+ }
+ value.addProperty(new DeprecatedProperty(description));
}
else
errorLog.log(annotation.location, "Unknown annotation.");
}
private boolean hasErrors() {
- return !compilationContext.errorLog.isEmpty();
+ return !compilationContext.errorLog.hasNoErrors();
}
public void compile(
module.setClasses(classes);
module.setModuleInitializer(moduleInitializer);
module.setBranchPoints(elaboration.branchPoints);
+ if(compilationContext.errorLog.hasErrorsOrWarnings())
+ module.setWarnings(compilationContext.errorLog.getErrors());
if(SCLCompilerConfiguration.ENABLE_TIMING) {
phaseFinished("Code generation");
compilationContext.errorLog.log(c.getDemandLocation(),
"Constraint <"+c.constraint+"> is not given and cannot be derived.");
}
- if(compilationContext.errorLog.isEmpty()) { // To prevent exceptions
+ if(compilationContext.errorLog.hasNoErrors()) { // To prevent exceptions
expression = ExpressionAugmentation.augmentSolved(
red.solvedConstraints,
expression);
}
}
else {
- if(compilationContext.errorLog.isEmpty()) // To prevent exceptions
+ if(compilationContext.errorLog.hasNoErrors()) // To prevent exceptions
expression = expression.decomposeMatching();
}
expression = expression.closure(vars.toArray(new TVar[vars.size()]));
}
if(value == null)
return new EError(location);
+ String deprecatedDescription = value.isDeprecated();
+ if(deprecatedDescription != null)
+ errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
return new EConstant(location, value);
}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions.annotations;
+
+import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVar;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+
+public class AnnotationUtils {
+ public static String extractString(Expression expression) {
+ if(expression instanceof EVar)
+ return ((EVar)expression).name;
+ else if(expression instanceof EStringLiteral) {
+ EStringLiteral literal = (EStringLiteral)expression;
+ if(literal.strings.length == 1)
+ return literal.strings[0];
+ }
+ else if(expression instanceof ELiteral) {
+ ELiteral literal = (ELiteral)expression;
+ if(literal.getValue() instanceof StringConstant) {
+ StringConstant constant = (StringConstant)literal.getValue();
+ return constant.getValue();
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.modules;
+
+public class DeprecatedProperty implements SCLValueProperty {
+ public final String description;
+
+ public DeprecatedProperty(String description) {
+ this.description = description;
+ }
+}
return true;
return false;
}
+
+ public String isDeprecated() {
+ for(SCLValueProperty property : properties)
+ if(property instanceof DeprecatedProperty)
+ return ((DeprecatedProperty)property).description;
+ return null;
+ }
public void setDocumentation(String documentation) {
this.documentation = documentation;
TypeAst typeAst = (TypeAst)parser.parseType();
TypeTranslationContext context = new TypeTranslationContext(compilationContext);
Type type = context.toType(typeAst);
- if(compilationContext.errorLog.isEmpty())
+ if(compilationContext.errorLog.hasNoErrors())
return type;
} catch(SCLSyntaxErrorException e) {
compilationContext.errorLog.log(e.location, e.getMessage());
public final long location;
public final String description;
+ public final ErrorSeverity severity;
- public CompilationError(long location, String description) {
+ public CompilationError(long location, String description, ErrorSeverity severity) {
if(description == null)
throw new NullPointerException();
this.location = location;
this.description = description;
+ this.severity = severity;
}
+ public CompilationError(long location, String description) {
+ this(location, description, ErrorSeverity.ERROR);
+ }
+
public CompilationError(long location, Exception exception) {
this(location, exceptionToString(exception));
}
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
public class ErrorLog {
- ArrayList<CompilationError> errors = new ArrayList<CompilationError>();
+ ArrayList<CompilationError> errors = new ArrayList<CompilationError>();
+ int errorCount;
long exceptionPosition = Locations.NO_LOCATION;
public void log(String message) {
- errors.add(new CompilationError(message));
+ log(new CompilationError(message));
}
public void log(CompilationError error) {
errors.add(error);
+ if(error.severity == ErrorSeverity.ERROR)
+ ++errorCount;
}
public void log(long locatable, String description) {
log(new CompilationError(locatable, description));
}
+
+ public void logWarning(long locatable, String description) {
+ log(new CompilationError(locatable, description, ErrorSeverity.WARNING));
+ }
public void log(Exception e) {
long location = Locations.NO_LOCATION;
log(new CompilationError(location, e));
}
- public boolean isEmpty() {
- return errors.isEmpty();
+ public boolean hasNoErrors() {
+ return errorCount == 0;
+ }
+
+ public boolean hasErrors() {
+ return errorCount > 0;
+ }
+
+ public boolean hasErrorsOrWarnings() {
+ return !errors.isEmpty();
}
public CompilationError[] getErrors() {
}
public String getErrorsAsString() {
+ Collections.sort(errors);
StringBuilder b = new StringBuilder();
for(CompilationError error : errors)
b.append(error.description).append('\n');
}
public int getErrorCount() {
- return errors.size();
+ return errorCount;
}
}
--- /dev/null
+package org.simantics.scl.compiler.errors;
+
+public enum ErrorSeverity {
+ ERROR,
+ WARNING
+}
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.environment.filter.NamespaceFilter;
+import org.simantics.scl.compiler.errors.CompilationError;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.top.ModuleInitializer;
import org.simantics.scl.compiler.types.TCon;
THashMap<String, MappingRelation> mappingRelations = new THashMap<String, MappingRelation>();
ArrayList<ImportDeclaration> dependencies = new ArrayList<ImportDeclaration>();
THashMap<String, BranchPoint[]> branchPoints;
-
+ CompilationError[] warnings = CompilationError.EMPTY_ARRAY;
+
Map<String, byte[]> classes = Collections.emptyMap();
ModuleInitializer moduleInitializer;
@Override
public void dispose() {
-
+ }
+
+ public void setWarnings(CompilationError[] warnings) {
+ this.warnings = warnings;
+ }
+
+ public CompilationError[] getWarnings() {
+ return warnings;
}
}
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
+import org.simantics.scl.compiler.errors.CompilationError;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.top.ModuleInitializer;
import org.simantics.scl.compiler.types.TCon;
public THashMap<String, BranchPoint[]> getBranchPoints() {
return null;
}
+
+ @Override
+ public CompilationError[] getWarnings() {
+ return CompilationError.EMPTY_ARRAY;
+ }
}
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.environment.filter.NamespaceFilter;
+import org.simantics.scl.compiler.errors.CompilationError;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.top.ModuleInitializer;
import org.simantics.scl.compiler.types.TCon;
THashMap<String, BranchPoint[]> getBranchPoints();
void dispose();
+
+ CompilationError[] getWarnings();
}
listener),
moduleName,
getJavaReferenceValidator());
- if(compiler.getErrorLog().isEmpty())
+ if(compiler.getErrorLog().hasNoErrors())
return new Success<Module>(compiler.getModule());
else {
LOGGER.error("While compiling " + getModuleName() + ":");
{
TranslationContext context = new TranslationContext(compilationContext, localEnvironment);
expression = expression.resolve(context);
- if(!errorLog.isEmpty())
+ if(!errorLog.hasNoErrors())
throw new SCLExpressionCompilationException(errorLog.getErrors());
}
expectedType.addPolarity(Polarity.POSITIVE);
context.solveSubsumptions(expression.location);
- if(!errorLog.isEmpty())
+ if(!errorLog.hasNoErrors())
throw new SCLExpressionCompilationException(errorLog.getErrors());
if(decorateExpression && Types.canonical(expectedEffect) != Types.NO_EFFECTS) {
ExpressionDecorator decorator =
expression = context.solveConstraints(environment, expression);
expressionType = expression.getType();
- if(!errorLog.isEmpty())
+ if(!errorLog.hasNoErrors())
throw new SCLExpressionCompilationException(errorLog.getErrors());
if(localEnvironment != null)
new SimplificationContext(compilationContext, DummyJavaReferenceValidator.INSTANCE);
expression = expression.simplify(context);
- if(!errorLog.isEmpty())
+ if(!errorLog.hasNoErrors())
throw new SCLExpressionCompilationException(errorLog.getErrors());
if(SCLCompilerConfiguration.SHOW_EXPRESSION_BEFORE_EVALUATION)
instance Read String where
read str = str
+@deprecated
"`splitString text pattern` splits the string into a list of string where the parts are sepratated in the original list by the given pattern."
splitString :: String -> String -> [String]
splitString source pattern = arrayToList $ splitString_ source pattern
reg.put("find", Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/find.png") );
reg.put("disk", Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/disk.png") );
reg.put("error", Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/error.png") );
+ reg.put("warning", Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/warning.png") );
}
@Override
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModel;
import org.simantics.scl.compiler.errors.CompilationError;
+import org.simantics.scl.compiler.errors.DoesNotExist;
+import org.simantics.scl.compiler.errors.ErrorSeverity;
import org.simantics.scl.compiler.errors.Failable;
import org.simantics.scl.compiler.errors.Failure;
import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.errors.Success;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.module.repository.ModuleRepository;
import org.simantics.scl.compiler.module.repository.UpdateListener;
Failure failure = (Failure)result;
setAnnotations(Arrays.asList(failure.errors));
}
- else {
+ else if(result == DoesNotExist.INSTANCE)
setAnnotations(Collections.<CompilationError>emptyList());
- }
+ else
+ setAnnotations(Arrays.asList(result.getResult().getWarnings()));
}
protected void setAnnotations(List<CompilationError> errors) {
synchronized(getLockObject()) {
removeAllAnnotations();
for(CompilationError error : errors) {
- Annotation annotation = new Annotation("org.eclipse.ui.workbench.texteditor.error", true,
- error.description);
+ Annotation annotation = new Annotation(
+ error.severity == ErrorSeverity.ERROR ?
+ "org.eclipse.ui.workbench.texteditor.error" :
+ "org.eclipse.ui.workbench.texteditor.warning",
+ true, error.description);
int begin = Locations.beginOf(error.location);
int end = Locations.endOf(error.location);
Position position = new Position(begin, end - begin);
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Control;
import org.simantics.scl.compiler.errors.CompilationError;
+import org.simantics.scl.compiler.errors.DoesNotExist;
import org.simantics.scl.compiler.errors.Failable;
import org.simantics.scl.compiler.errors.Failure;
import org.simantics.scl.compiler.module.Module;
boolean disposed = false;
AtomicBoolean refreshInProgress = new AtomicBoolean(false);
- THashMap<String, Failure> currentFailures = new THashMap<String, Failure>();
+ THashMap<String, CompilationError[]> currentFailures = new THashMap<String, CompilationError[]>();
THashMap<String, UpdateListener> updateListeners = new THashMap<String, UpdateListener>();
@Override
synchronized(currentFailures) {
if(result instanceof Failure) {
Failure failure = (Failure)result;
- currentFailures.put(moduleName, failure);
+ currentFailures.put(moduleName, failure.errors);
}
- else
+ else if(result == DoesNotExist.INSTANCE) {
if(currentFailures.remove(moduleName) == null)
return;
+ }
+ else {
+ CompilationError[] warnings = result.getResult().getWarnings();
+ if(warnings.length == 0) {
+ if(currentFailures.remove(moduleName) == null)
+ return;
+ }
+ else {
+ currentFailures.put(moduleName, warnings);
+ }
+ }
}
refresh();
}
String[] moduleNames = currentFailures.keySet().toArray(new String[currentFailures.size()]);
Arrays.sort(moduleNames);
for(String moduleName : moduleNames) {
- Failure failure = currentFailures.get(moduleName);
- for(CompilationError error : failure.errors)
+ CompilationError[] errors = currentFailures.get(moduleName);
+ for(CompilationError error : errors)
result.add(new SCLIssuesTableEntry(moduleName, error));
if(result.size() >= MAX_ISSUE_COUNT)
break;
public int compareTo(SCLIssuesTableEntry o) {
if(this == o)
return 0;
- int cmp = moduleName.compareTo(o.moduleName);
+ int cmp = error.severity.compareTo(o.error.severity);
+ if(cmp != 0)
+ return cmp;
+ cmp = moduleName.compareTo(o.moduleName);
if(cmp != 0)
return cmp;
cmp = Locations.compare(error.location, o.error.location);
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
+import org.simantics.scl.compiler.errors.ErrorSeverity;
import org.simantics.scl.osgi.SCLOsgi;
import org.simantics.scl.ui.Activator;
import org.simantics.scl.ui.editor2.OpenSCLDefinition;
}
@Override
public Image getImage(Object element) {
- return imageRegistry.get("error");
+ SCLIssuesTableEntry entry = (SCLIssuesTableEntry)element;
+ return entry.error.severity == ErrorSeverity.ERROR
+ ? imageRegistry.get("error")
+ : imageRegistry.get("warning");
}
});