From: Marko Luukkainen Date: Wed, 20 Feb 2019 17:14:33 +0000 (+0000) Subject: Merge "Use STR.Component base type for resolving actual type." X-Git-Tag: v1.43.0~136^2~192 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=e2f997281a0eb7c0108000e5462659f5906d3e23;hp=761883de70ce4cbc6ff459893a014368b077abfa;p=simantics%2Fplatform.git Merge "Use STR.Component base type for resolving actual type." --- diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java index 2dcb6e00a..9b0befc78 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java @@ -26,6 +26,7 @@ import org.simantics.db.layer0.exception.PendingVariableException; import org.simantics.db.layer0.function.All; import org.simantics.db.layer0.request.PropertyInfo; import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.scl.SCLDatabaseException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.layer0.Layer0; import org.simantics.utils.Development; @@ -149,9 +150,11 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { try { - return (T)getValueAccessor(graph).getValue(graph, this, binding); - } catch (PendingVariableException e) { - throw e; + return (T) getValueAccessor(graph).getValue(graph, this, binding); + } catch (SCLDatabaseException e) { // these can be thrown when compiling e.g. derived properties + throw e; + } catch (MissingVariableValueException | PendingVariableException e) { + throw e; } catch (Throwable t) { throw new MissingVariableValueException(t); } diff --git a/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdapterRegistry2.java b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdapterRegistry2.java index 0e52b8a41..578b42a61 100644 --- a/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdapterRegistry2.java +++ b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdapterRegistry2.java @@ -16,9 +16,10 @@ import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -48,6 +49,9 @@ import org.simantics.db.services.adaption.reflection.StaticMethodAdapter; import org.simantics.db.services.adaption.reflection.ThisResource2; import org.simantics.scl.reflection.OntologyVersions; import org.simantics.utils.FileUtils; +import org.simantics.utils.threads.ThreadUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; @@ -60,6 +64,8 @@ import org.xml.sax.SAXParseException; public class AdapterRegistry2 { + private static final Logger LOGGER = LoggerFactory.getLogger(AdapterRegistry2.class); + public static final String ADAPTERS_FILE = "adapters.xml"; public static final String ADAPTERS = "adapters"; @@ -77,8 +83,7 @@ public class AdapterRegistry2 { public static final String CONSTRUCTOR = "constructor"; static private AdapterRegistry2 instance = new AdapterRegistry2(); - Collection installers = new ArrayList(); - Map installerSources = new HashMap(); + ConcurrentHashMap installerSources = new ConcurrentHashMap<>(); Collection exceptions = new ArrayList(); public static AdapterRegistry2 getInstance() { @@ -86,11 +91,10 @@ public class AdapterRegistry2 { } private void addInstaller(AdapterInstaller installer, String sourceDesc) { - installers.add(installer); installerSources.put(installer, sourceDesc); } - private void handleException(Exception e, String fileName) { + private static void handleException(Exception e, String fileName) { System.err.println("At " + fileName); e.printStackTrace(); } @@ -336,7 +340,7 @@ public class AdapterRegistry2 { s.syncRequest(new ReadRequest() { @Override public void run(ReadGraph g) { - for(AdapterInstaller t : installers) { + for(AdapterInstaller t : installerSources.keySet()) { try { t.install(g, service); } catch (Exception e) { @@ -416,7 +420,7 @@ public class AdapterRegistry2 { } public void initialize(BundleContext context) { - + LOGGER.info("Initializing"); try { DocumentBuilderFactory factory = @@ -433,54 +437,63 @@ public class AdapterRegistry2 { } // TODO Listen bundles (install/uninstall) + List> waitFor = new ArrayList<>(); if (exceptions.isEmpty()) for (final Bundle b : context.getBundles()) { - URL file = b.getEntry(ADAPTERS_FILE); - if (file != null) { - String fileName = new Path(b.getLocation()).append(file.getPath()).toString(); - try { - DocumentBuilder builder = factory.newDocumentBuilder(); - builder.setErrorHandler(new ErrorHandler() { - - @Override - public void error(SAXParseException exception) - throws SAXException { - // TODO Put this error somewhere - System.err.println("Parse error at " - + b.getSymbolicName() + "/adapters.xml" + - " line " + exception.getLineNumber() + - " column " + exception.getColumnNumber() + ":"); - System.err.println(exception.getMessage()); - } - - @Override - public void fatalError(SAXParseException exception) - throws SAXException { - error(exception); - } - - @Override - public void warning(SAXParseException exception) - throws SAXException { - error(exception); - } - - }); - - //System.out.println("bundle=" + b.getSymbolicName()); - String text = FileUtils.getContents(file); - text = OntologyVersions.getInstance().currentVersion(text); - StringReader reader = new StringReader( text ); - InputSource inputSource = new InputSource( reader ); - Document doc = builder.parse( inputSource ); - reader.close(); - handleAdaptersDocument(loader(b), doc, fileName); - } catch (Exception e) { - handleException(e, fileName); - + Future submit = ThreadUtils.getNonBlockingWorkExecutor().submit(() -> { + URL file = b.getEntry(ADAPTERS_FILE); + if (file != null) { + String fileName = new Path(b.getLocation()).append(file.getPath()).toString(); + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setErrorHandler(new ErrorHandler() { + + @Override + public void error(SAXParseException exception) throws SAXException { + // TODO Put this error somewhere + System.err.println("Parse error at " + b.getSymbolicName() + "/adapters.xml" + + " line " + exception.getLineNumber() + " column " + + exception.getColumnNumber() + ":"); + System.err.println(exception.getMessage()); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + error(exception); + } + + @Override + public void warning(SAXParseException exception) throws SAXException { + error(exception); + } + + }); + + // System.out.println("bundle=" + b.getSymbolicName()); + String text = FileUtils.getContents(file); + text = OntologyVersions.getInstance().currentVersion(text); + StringReader reader = new StringReader(text); + InputSource inputSource = new InputSource(reader); + Document doc = builder.parse(inputSource); + reader.close(); + handleAdaptersDocument(loader(b), doc, fileName); + } catch (Exception e) { + handleException(e, fileName); + + } } - } + }); + waitFor.add(submit); + } + // Let's wait in here + waitFor.forEach(f -> { + try { + f.get(); + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Could not wait adapters to load", e); } + }); + LOGGER.info("Adapters installed"); } catch (Exception e) { handleException(e, "(no file name available)"); } diff --git a/bundles/org.simantics.document.base.ontology/graph/Components.pgraph b/bundles/org.simantics.document.base.ontology/graph/Components.pgraph index 65a75d288..e89d74589 100644 --- a/bundles/org.simantics.document.base.ontology/graph/Components.pgraph +++ b/bundles/org.simantics.document.base.ontology/graph/Components.pgraph @@ -54,6 +54,7 @@ DOC.SCLValue compileSimupediaSCLHandlerValueExpression self""" "Variable -> String" @L0.assert L0.ConvertsToValueWith DOC.Functions.sclHandlerValue : L0.ExternalValue diff --git a/bundles/org.simantics.document.server/scl/Document/All.scl b/bundles/org.simantics.document.server/scl/Document/All.scl index 6eaf328a3..a90a24bcb 100644 --- a/bundles/org.simantics.document.server/scl/Document/All.scl +++ b/bundles/org.simantics.document.server/scl/Document/All.scl @@ -144,6 +144,7 @@ importJava "org.simantics.document.server.Functions" where stateVariable :: Variable -> Variable compileDocumentSCLValueExpression :: Variable -> String + compileDocumentSCLHandlerValueExpression :: Variable -> String primitiveProperties :: DocumentProperties diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java index 186edd252..d5a727ffa 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java @@ -1381,6 +1381,15 @@ public class Functions { } } + public static String compileDocumentSCLHandlerValueExpression(ReadGraph graph, Variable context) { + try { + ServerSCLHandlerValueRequest.compile(graph, context); + return ""; + } catch (Exception e) { + return resolveIssueMessage(e); + } + } + private static String resolveIssueMessage(Exception e) { if (e instanceof ImportFailureException) return ""; diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java index 924c7c252..1da7fe647 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java @@ -166,8 +166,8 @@ public class SWTMouseEventAdapter extends AbstractEventAdapter implements MouseL sender, e.time & 0xffffffff, MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e), - MouseWheelMovedEvent.WHEEL_UNIT_SCROLL, - 0, + MouseWheelMovedEvent.WHEEL_UNIT_SCROLL, + MouseWheelMovedEvent.SCROLL_AMOUNT_ZERO, e.count )); } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java index 048e0840e..1c4b22ee0 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java @@ -3,6 +3,8 @@ package org.simantics.modeling.ui.componentTypeEditor; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,6 +49,7 @@ import org.simantics.layer0.Layer0; import org.simantics.modeling.userComponent.ComponentTypeCommands; import org.simantics.scl.runtime.function.Function2; import org.simantics.scl.runtime.function.Function4; +import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ErrorLogger; public class ComponentTypeViewerData { @@ -373,18 +376,32 @@ public class ComponentTypeViewerData { if (validator != null) { org.eclipse.swt.widgets.Listener validationListener = new org.eclipse.swt.widgets.Listener() { + + private ScheduledFuture future; + @Override public void handleEvent(Event e) { final String newValue = text.getText(); - String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue); - if (error != null) { - text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED)); - text.setToolTipText(error); - return; - } else { - text.setBackground(null); - text.setToolTipText(null); - } + if (future != null && !future.isCancelled()) + future.cancel(true); + future = ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> { + String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue); + if (!text.isDisposed()) { + text.getDisplay().asyncExec(() -> { + if (!text.isDisposed()) { + if (error != null) { + text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED)); + text.setToolTipText(error); + return; + } else { + text.setBackground(null); + text.setToolTipText(null); + } + } + + }); + } + }, 500, TimeUnit.MILLISECONDS); } }; text.addListener(SWT.Modify, validationListener); diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java index 869d5e32a..0f7bff396 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java @@ -32,14 +32,25 @@ import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.request.PropertyInfo; +import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; +import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; +import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; +import org.simantics.modeling.scl.CompileProceduralSCLMonitorRequest; +import org.simantics.modeling.scl.CompileSCLMonitorRequest; import org.simantics.modeling.userComponent.ComponentTypeCommands; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function1; import org.simantics.scl.runtime.function.Function4; import org.simantics.structural.stubs.StructuralResource2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DerivedPropertiesSection implements ComponentTypeViewerSection { private static final String[] COLUMN_NAMES = { @@ -62,6 +73,8 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { } }; + private static final Logger LOGGER = LoggerFactory.getLogger(DerivedPropertiesSection.class); + ComponentTypeViewerData data; Table table; TableColumn[] columns; @@ -267,23 +280,33 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(componentType)); - + // TODO: this is a bit hackish but should get the job done in most parts and + // importantly indicates something for the user + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheAsyncListener.instance()); + Variable parent = new StandardGraphChildVariable(null, null, componentType) { + + public Resource getType(ReadGraph graph) throws DatabaseException { + return componentType; + }; + + public Variable getPossibleProperty(ReadGraph graph, String name) throws DatabaseException { + Variable prop = super.getPossibleProperty(graph, name); + if (prop != null) { + return prop; + } else { + return getChild(graph, name); + } + }; + }; + for(Resource literal : graph.getAssertedObjects(componentType, relation)) { try { - // TODO validation + Variable context = new StandardGraphPropertyVariable(parent, null, null, info, literal); if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) { - //Layer0 L0 = Layer0.getInstance(graph); - //Resource environment = graph.getPossibleObject(literal, L0.SCLValue_environment); - //ContextModule context = graph.sync(new TypeMonitorContextRequest(componentType)); - //String SCLMain = graph.syncRequest(new SCLMainModuleRequest(indexRoot)); - //CompilationContext cc = new CompilationContext(environment, context, SCLMain); - //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); + CompileProceduralSCLMonitorRequest.compileAndEvaluate(graph, context); } else { - //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph); - //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); - //graph.syncRequest(new CompileSCLMonitorRequest(graph, context)); + compileAndEvaluate(graph, context, expression); } } catch (Exception e) { @@ -292,22 +315,39 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { if(index > 0) msg = msg.substring(index); return msg; } - } - return null; - } }); } catch (DatabaseException e) { - e.printStackTrace(); + LOGGER.error("Could not validate ", e); } - return null; - } + public static void compileAndEvaluate(ReadGraph graph, Variable context, String expression) throws DatabaseException { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); + try { + CompileSCLMonitorRequest compileSCLMonitorRequest = new CompileSCLMonitorRequest(graph, context) { + @Override + protected String getExpressionText(ReadGraph graph) throws DatabaseException { + return expression; + } + }; + Function1 exp = graph.syncRequest(compileSCLMonitorRequest); + sclContext.put("graph", graph); + //return exp.apply(context.getParent(graph)); + } catch (DatabaseException e) { + throw (DatabaseException)e; + } catch (Throwable t) { + throw new DatabaseException(t); + } finally { + sclContext.put("graph", oldGraph); + } + } + @Override public void update(ComponentTypePropertiesResult result) { if (table.isDisposed()) diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java index 9b0980600..d3ab61355 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java @@ -42,20 +42,19 @@ public class EventQueue implements IEventQueue, IEventHandler { return EventTypes.AnyMask; } - /** - * - */ - private MouseWheelMovedEvent lastMouseWheelMovedEvent; - private static final String DISABLE_DUPLICATE_REMOVAL = "org.simantics.scenegraph.g2d.events.disableDuplicateMouseWheelEvent"; private static final boolean IGNORE_DUPLICATE = !Boolean.parseBoolean(System.getProperty(DISABLE_DUPLICATE_REMOVAL)); private boolean ignoreDuplicateMouseWheelMovedEvent(Event e) { if (IGNORE_DUPLICATE && e instanceof MouseWheelMovedEvent) { - if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) { + MouseWheelMovedEvent event = (MouseWheelMovedEvent) e; + // if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) { + // apparently this is a better way to distinguish between SWT & AWT events + // SWT based event constructs the scrollAmount to = 0 + // See org.simantics.g2d.event.adapter.SWTMouseEventAdapter.mouseScrolled(MouseEvent) L171 + if (event.scrollAmount != MouseWheelMovedEvent.SCROLL_AMOUNT_ZERO) { return true; } - lastMouseWheelMovedEvent = (MouseWheelMovedEvent) e; } return false; } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/MouseEvent.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/MouseEvent.java index 92c97b787..8070ae358 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/MouseEvent.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/MouseEvent.java @@ -154,6 +154,8 @@ public abstract class MouseEvent extends Event { private static final long serialVersionUID = -7896477913481842708L; + public static final int SCROLL_AMOUNT_ZERO = 0; + /** * Constant representing scrolling by "units" (like scrolling with the * arrow keys) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java index ba78a3548..7767b5d20 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java @@ -13,11 +13,19 @@ public class Names { public static final Name Builtin_fail = Name.create(Types.BUILTIN, "fail"); public static final Name Builtin_runProc = Name.create(Types.BUILTIN, "runProc"); public static final Name Builtin_createCHRContext = Name.create(Types.BUILTIN, "createCHRContext"); + public static final Name Builtin_Just = Name.create("Builtin", "Just"); + public static final Name Builtin_Nothing = Name.create("Builtin", "Nothing"); public static final Name Data_XML_createElement = Name.create("Data/XML", "createElement"); public static final Type Data_XML_Element = Types.con("Data/XML", "Element"); public static final TCon Expressions_Context_Context = Types.con("Expressions/Context", "Context"); public static final Name Expressions_Context_contextGet = Name.create("Expressions/Context", "contextGet"); public static final Name JavaBuiltin_unsafeCoerce = Name.create("JavaBuiltin", "unsafeCoerce"); + public static final TCon Json_Json = Types.con("Data/Json", "Json"); + public static final Name Json_fromJson = Name.create("Data/Json", "fromJson"); + public static final Name Json_toJson = Name.create("Data/Json", "toJson"); + public static final Name Json_lookupJsonField = Name.create("Data/Json", "lookupJsonField"); + public static final Name Json_JsonObject = Name.create("Data/Json", "JsonObject"); + public static final Name Json_JsonField = Name.create("Data/Json", "JsonField"); public static final Name MList_add = Name.create("MList", "add"); public static final Name MList_create = Name.create("MList", "create"); public static final Name MList_freeze = Name.create("MList", "freeze"); @@ -36,15 +44,19 @@ public class Names { public static final Name Prelude_bindE = Name.create("Prelude", "bindE"); public static final Name Prelude_build = Name.create("Prelude", "build"); public static final Name Prelude_concatMap = Name.create("Prelude", "concatMap"); + public static final Name Prelude_dot = Name.create("Prelude", "."); public static final Name Prelude_dollar = Name.create("Prelude", "$"); public static final Name Prelude_elem = Name.create("Prelude", "elem"); public static final Name Prelude_elemMaybe = Name.create("Prelude", "elemMaybe"); public static final Name Prelude_emptyList = Name.create("Prelude", "emptyList"); + public static final Name Prelude_filterJust = Name.create("Prelude", "filterJust"); public static final Name Prelude_foldl = Name.create("Prelude", "foldl"); public static final Name Prelude_fromDouble = Name.create("Prelude", "fromDouble"); public static final Name Prelude_fromInteger = Name.create("Prelude", "fromInteger"); + public static final Name Prelude_fromJust = Name.create("Prelude", "fromJust"); public static final Name Prelude_guardList = Name.create("Prelude", "guardList"); public static final Name Prelude_iterList = Name.create("Prelude", "iterList"); + public static final Name Prelude_map = Name.create("Prelude", "map"); public static final Name Prelude_mapFirst = Name.create("Prelude", "mapFirst"); public static final Name Prelude_mapList = Name.create("Prelude", "mapList"); public static final Name Prelude_neg = Name.create("Prelude", "neg"); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java index 56e8eb3b6..621c97684 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java @@ -374,7 +374,8 @@ public class Elaboration { } boolean trivialDataType = dataTypeAst.constructors.length == 1 && - dataTypeAst.constructors[0].parameters.length == 1; + dataTypeAst.constructors[0].parameters.length == 1 && + !external; if(className == null && !trivialDataType) className = compilationContext.namingPolicy.getDataTypeClassName(dataTypeAst.name); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/InstanceDerivers.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/InstanceDerivers.java index b450766a6..43f9b3385 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/InstanceDerivers.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/InstanceDerivers.java @@ -1,5 +1,6 @@ package org.simantics.scl.compiler.internal.deriving; +import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.Types; @@ -13,6 +14,7 @@ public class InstanceDerivers { MAP.put(Types.IO, new IODeriver()); MAP.put(Types.ORD, new OrdDeriver()); MAP.put(Types.SHOW, new ShowDeriver()); + MAP.put(Names.Json_Json, new JsonDeriver()); } public static InstanceDeriver get(TCon typeClass) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java new file mode 100644 index 000000000..24f8b3162 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java @@ -0,0 +1,218 @@ +package org.simantics.scl.compiler.internal.deriving; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.datatypes.Constructor; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.constants.StringConstant; +import org.simantics.scl.compiler.elaboration.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.EApply; +import org.simantics.scl.compiler.elaboration.expressions.EConstant; +import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; +import org.simantics.scl.compiler.elaboration.expressions.ELiteral; +import org.simantics.scl.compiler.elaboration.expressions.ERecord; +import org.simantics.scl.compiler.elaboration.expressions.EVar; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +import org.simantics.scl.compiler.elaboration.modules.TypeAlias; +import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; +import org.simantics.scl.compiler.environment.AmbiguousNameException; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.environment.Environments; +import org.simantics.scl.compiler.errors.ErrorLog; +import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst; +import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst; +import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; +import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst; +import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository; +import org.simantics.scl.compiler.internal.parsing.types.TVarAst; +import org.simantics.scl.compiler.types.TApply; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +class JsonDeriver implements InstanceDeriver { + + @Override + public void derive( + ErrorLog errorLog, + Environment environment, + ArrayList instancesAst, + DDerivingInstanceAst der) { + // Analyze + if(der.types.length != 1) { + errorLog.log(der.location, "Invalid number of parameters to " + der.name); + return; + } + TVarAst headType = DerivingUtils.getHeadType(der.types[0]); + if(headType == null) { + errorLog.log(der.types[0].location, "Cannot derive Json instance for the type " + headType + "."); + return; + } + TCon con; + try { + con = Environments.getTypeDescriptorName(environment, headType.name); + } catch (AmbiguousNameException e1) { + errorLog.log(headType.location, e1.getMessage()); + return; + } + if(con == null) { + errorLog.log(headType.location, "Couldn't resolve " + headType.name); + return; + } + TypeDescriptor tdesc = environment.getTypeDescriptor(con); + if(tdesc == null) { + errorLog.log(headType.location, "Didn't find type constructor for " + headType.name); + return; + } + if(tdesc instanceof TypeAlias) { + errorLog.log(headType.location, "Cannot derive instance for a type alias."); + return; + } + TypeConstructor tcon = (TypeConstructor)tdesc; + if(tcon.isOpen) { + errorLog.log(headType.location, "Cannot derive instance for open data types."); + return; + } + + if(tcon.constructors.length != 1) { + errorLog.log(headType.location, "Data must have exactly one constructor for deriving to work."); + return; + } + Constructor constructor = tcon.constructors[0]; + if(constructor.recordFieldNames == null) { + errorLog.log(headType.location, "Data must have a record constructor for deriving to work."); + return; + } + + DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types); + ValueRepository valueDefs = new ValueRepository(); + + SCLValue fromJson = environment.getValue(Names.Json_fromJson); + SCLValue toJson = environment.getValue(Names.Json_toJson); + SCLValue lookupJsonField = environment.getValue(Names.Json_lookupJsonField); + SCLValue JsonObject = environment.getValue(Names.Json_JsonObject); + SCLValue JsonField = environment.getValue(Names.Json_JsonField); + + SCLValue Just = environment.getValue(Names.Builtin_Just); + SCLValue fromJust = environment.getValue(Names.Prelude_fromJust); + SCLValue map = environment.getValue(Names.Prelude_map); + SCLValue filterJust = environment.getValue(Names.Prelude_filterJust); + SCLValue dot = environment.getValue(Names.Prelude_dot); + + // Collect all relevant information about the constructor + String constructorName = constructor.name.name; + int fieldCount = constructor.parameterTypes.length; + String[] fieldNames = constructor.recordFieldNames; + boolean[] isOptional = new boolean[fieldCount]; + boolean hasAtLeastOneOptional = false; + for(int i=0;i Json -> Maybe Json +lookupJsonField fieldName (JsonObject fields) = mapFirst selector fields + where + selector (JsonField name value) | name == fieldName = Just value + selector _ = Nothing + deriving instance Show Json deriving instance Show JsonField diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/SCLModuleEditor2.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/SCLModuleEditor2.java index 1b2096eb9..9aa1f0ddd 100644 --- a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/SCLModuleEditor2.java +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/SCLModuleEditor2.java @@ -26,10 +26,12 @@ import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.IUpdate; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.TextNavigationAction; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.simantics.scl.ui.editor.SCLSourceViewerConfigurationNew; import org.simantics.scl.ui.editor.completion.SCLTextEditorEnvironment; import org.simantics.scl.ui.editor2.iterator.DocumentCharacterIterator; import org.simantics.scl.ui.editor2.iterator.JavaWordIterator; +import org.simantics.scl.ui.outline.SCLModuleOutlinePage; import com.ibm.icu.text.BreakIterator; @@ -46,12 +48,15 @@ public class SCLModuleEditor2 extends TextEditor { protected ResourceManager resourceManager; private DefaultCharacterPairMatcher matcher; + private SCLModuleOutlinePage outline; + public SCLModuleEditor2() { super(); resourceManager = new LocalResourceManager(JFaceResources.getResources()); SCLSourceViewerConfigurationNew sourceViewerConfiguration = new SCLSourceViewerConfigurationNew(resourceManager); setDocumentProvider(new SCLModuleEditor2DocumentProvider(sourceViewerConfiguration)); setSourceViewerConfiguration(sourceViewerConfiguration); + outline = new SCLModuleOutlinePage(this); } @Override @@ -136,7 +141,16 @@ public class SCLModuleEditor2 extends TextEditor { public IDocument getDocument() { return getSourceViewer().getDocument(); } - + + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Class adapter) { + if (IContentOutlinePage.class.equals(adapter)) { + return (T) outline; + } + return super.getAdapter(adapter); + } + /** * Text navigation action to navigate to the next sub-word. * diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/outline/SCLModuleOutlinePage.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/outline/SCLModuleOutlinePage.java index d333f235a..80e34c374 100644 --- a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/outline/SCLModuleOutlinePage.java +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/outline/SCLModuleOutlinePage.java @@ -1,96 +1,144 @@ package org.simantics.scl.ui.outline; -import org.eclipse.jface.viewers.ILabelProvider; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.ui.part.Page; -import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.ui.views.contentoutline.ContentOutlinePage; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter; +import org.simantics.scl.compiler.errors.Failable; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.module.Module; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.compiler.source.ModuleSource; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.osgi.SCLOsgi; +import org.simantics.scl.ui.Activator; import org.simantics.scl.ui.editor2.SCLModuleEditor2; +import org.simantics.scl.ui.editor2.SCLModuleEditorInput; -public class SCLModuleOutlinePage extends Page implements IContentOutlinePage { +public class SCLModuleOutlinePage extends ContentOutlinePage { - private SCLOutlineViewer outlineViewer; + private TreeViewer outlineViewer; private SCLModuleEditor2 moduleEditor; - + private UpdateListener updateListener; + private LocalResourceManager resourceManager; + private Image publicImage; + private Image privateImage; + private Image typeImage; + public SCLModuleOutlinePage(SCLModuleEditor2 moduleEditor) { this.moduleEditor = moduleEditor; - } - - @Override - public void addSelectionChangedListener(ISelectionChangedListener listener) { - if (outlineViewer != null) - outlineViewer.addSelectionChangedListener(listener); - } - - @Override - public ISelection getSelection() { - if (outlineViewer != null) - outlineViewer.getSelection(); - return StructuredSelection.EMPTY; - } - - @Override - public void removeSelectionChangedListener(ISelectionChangedListener listener) { - if (outlineViewer != null) - outlineViewer.removeSelectionChangedListener(listener); - } - - @Override - public void setSelection(ISelection selection) { - if (outlineViewer != null) - outlineViewer.setSelection(selection); + resourceManager = new LocalResourceManager(JFaceResources.getResources()); + publicImage = resourceManager + .createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/public_co.gif")); + privateImage = resourceManager + .createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/private_co.gif")); + typeImage = resourceManager + .createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/typedef_obj.gif")); } @Override public void createControl(Composite parent) { - Tree tree = new Tree(parent, SWT.MULTI); - outlineViewer = new SCLOutlineViewer(tree); - + super.createControl(parent); + outlineViewer = getTreeViewer(); + SCLModuleOutlineProvider provider = new SCLModuleOutlineProvider(); + DelegatingStyledCellLabelProvider labelProvider = new DelegatingStyledCellLabelProvider(provider); outlineViewer.setContentProvider(provider); - outlineViewer.setLabelProvider(provider); - - outlineViewer.setInput(moduleEditor.getEditorInput()); + outlineViewer.setLabelProvider(labelProvider); + outlineViewer.addSelectionChangedListener(this); + + SCLModuleEditorInput input = (SCLModuleEditorInput) moduleEditor.getEditorInput(); + ModuleSource moduleSource = input.getAdapter(ModuleSource.class); + updateListener = new UpdateListener() { + + @Override + public void notifyAboutUpdate() { + parent.getDisplay().asyncExec(() -> { + if (!outlineViewer.getControl().isDisposed()) { + outlineViewer.refresh(); + } + }); + } + }; + Failable module = SCLOsgi.MODULE_REPOSITORY.getModule(moduleSource.getModuleName(), updateListener); + Module result = module.getResult(); + outlineViewer.setInput(result); } @Override - public Control getControl() { - if (outlineViewer != null) - outlineViewer.getControl(); - return null; + public void selectionChanged(SelectionChangedEvent event) { + super.selectionChanged(event); + ISelection selection = event.getSelection(); + TreeSelection tselection = (TreeSelection) selection; + if (tselection.getFirstElement() instanceof SCLValue) { + SCLValue value = (SCLValue) tselection.getFirstElement(); + long location = value.definitionLocation; + int begin = Locations.beginOf(location); + int end = Locations.endOf(location); + moduleEditor.selectAndReveal(begin, end - begin); + } else { +// TCon type = (TCon) tselection.getFirstElement(); +// type.loction; // this is missing? + } } @Override - public void setFocus() { - if (outlineViewer != null) - outlineViewer.getControl().setFocus(); + public void dispose() { + resourceManager.dispose(); + super.dispose(); } - protected class SCLOutlineViewer extends TreeViewer { - - public SCLOutlineViewer(Tree tree) { - super(tree); - setAutoExpandLevel(ALL_LEVELS); - setUseHashlookup(true); - } - - - } - - protected class SCLModuleOutlineProvider implements ITreeContentProvider, ILabelProvider { + protected class SCLModuleOutlineProvider implements ITreeContentProvider, IStyledLabelProvider { @Override public Object[] getElements(Object inputElement) { - return null; + Module result = (Module) inputElement; + List values = new ArrayList<>(); + result.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, value -> { + values.add(value); + }); + values.sort(new Comparator() { + + @Override + public int compare(SCLValue o1, SCLValue o2) { + int isPrivate = Boolean.compare(o1.isPrivate(), o2.isPrivate()); + if (isPrivate != 0) + return isPrivate; + else + return o1.getName().name.compareTo(o2.getName().name); + } + }); + List types = new ArrayList<>(); + result.findTypesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, type -> { + types.add(type); + }); + types.sort(new Comparator() { + + @Override + public int compare(TCon o1, TCon o2) { + return o1.name.compareTo(o2.name); + } + }); + List results = new ArrayList<>(); + results.addAll(types); + results.addAll(values); + return results.toArray(); } @Override @@ -110,7 +158,7 @@ public class SCLModuleOutlinePage extends Page implements IContentOutlinePage { @Override public void addListener(ILabelProviderListener listener) { - + } @Override @@ -120,23 +168,41 @@ public class SCLModuleOutlinePage extends Page implements IContentOutlinePage { @Override public void removeListener(ILabelProviderListener listener) { - + } @Override public Image getImage(Object element) { - return null; + if (element instanceof SCLValue) { + SCLValue value = (SCLValue) element; + if (value.isPrivate()) { + return privateImage; + } else { + return publicImage; + } + } else if (element instanceof TCon) { + return typeImage; + } else { + return null; + } } - @Override - public String getText(Object element) { - return null; - } - @Override public void dispose() { ITreeContentProvider.super.dispose(); } + @Override + public StyledString getStyledText(Object element) { + if (element instanceof SCLValue) { + SCLValue value = (SCLValue) element; + StyledString ss = new StyledString(value.getName().name); + ss.append(" :: " + value.getType().toString(), StyledString.COUNTER_STYLER); + return ss; + } else { + TCon type = (TCon) element; + return new StyledString(type.name); + } + } } } diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java index b2b4ea2ec..2552192ef 100644 --- a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java +++ b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java @@ -124,7 +124,6 @@ public class Synchronizer { while((cur = cur.getCause()) != null) { if(!(cur instanceof MissingVariableValueException)) { handler.reportProblem(cur.getMessage()); - break; } } } catch (Exception e) { diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java index 6e9975b68..5e564cc91 100644 --- a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java +++ b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java @@ -5,6 +5,7 @@ import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.IndexRoot; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; @@ -43,7 +44,14 @@ public class CompileStructuralValueRequest extends AbstractCompileStructuralValu sclContext.put("graph", graph); return exp.apply(context); } catch (Throwable t) { - throw new DatabaseException("Compiling structural value request for component=" + request.component + ", literal=" + request.literal + " and relation " + request.relation + " failed!", t); + String componentName = NameUtils.getSafeName(graph, request.component); + String literalName = NameUtils.getSafeName(graph, request.literal); + String relationName = NameUtils.getSafeName(graph, request.relation); + StringBuilder sb = new StringBuilder("Compiling structural value request for component ") + .append(componentName).append(" ").append(request.component).append(" , literal ") + .append(literalName).append(" ").append(request.literal).append(" and relation ") + .append(relationName).append(" ").append(request.relation).append(" failed!"); + throw new DatabaseException(sb.toString(), t); } finally { sclContext.put("graph", oldGraph); }