]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Use STR.Component base type for resolving actual type."
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Wed, 20 Feb 2019 17:14:33 +0000 (17:14 +0000)
committerGerrit Code Review <gerrit2@simantics>
Wed, 20 Feb 2019 17:14:33 +0000 (17:14 +0000)
19 files changed:
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java
bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdapterRegistry2.java
bundles/org.simantics.document.base.ontology/graph/Components.pgraph
bundles/org.simantics.document.server/scl/Document/All.scl
bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java
bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/MouseEvent.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/InstanceDerivers.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java [new file with mode: 0644]
bundles/org.simantics.scl.data/scl/Data/Json.scl
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/SCLModuleEditor2.java
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/outline/SCLModuleOutlinePage.java
bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java
bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java

index 2dcb6e00ab08871f296c7af6d5a498115edf7d60..9b0befc78442fa47d02022ca9e8863f01d1b5647 100644 (file)
@@ -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);
                }
index 0e52b8a417da4ebecf82c27369cf7581171c58e4..578b42a61d885d13cfb06e20e7c31436d00a6af2 100644 (file)
@@ -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<AdapterInstaller> installers = new ArrayList<AdapterInstaller>();
-    Map<AdapterInstaller, String> installerSources = new HashMap<AdapterInstaller, String>();
+    ConcurrentHashMap<AdapterInstaller, String> installerSources = new ConcurrentHashMap<>();
     Collection<Exception> exceptions = new ArrayList<Exception>();
 
     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<Future<?>> 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)");
         }
index 65a75d288777bc3556ef802cfa1d0219828aba9f..e89d7458926dfff6dac5e30b8f077498a47b9e53 100644 (file)
@@ -54,6 +54,7 @@ DOC.SCLValue <T L0.SCLValue
     DOC.Functions.sclValue : L0.ExternalValue
 
 DOC.HandlerSCLValue <T L0.SCLValue
+  @L0.scl L0.SCLValueType.validator """\self -> compileSimupediaSCLHandlerValueExpression self""" "Variable -> <ReadGraph> String"
   @L0.assert L0.ConvertsToValueWith
     DOC.Functions.sclHandlerValue : L0.ExternalValue
 
index 6eaf328a32d64cd67ba13e64ded08f915cc31a02..a90a24bcb62c30c55cad163eb3d242f869bec690 100644 (file)
@@ -144,6 +144,7 @@ importJava "org.simantics.document.server.Functions" where
     stateVariable :: Variable -> <ReadGraph> Variable
     
     compileDocumentSCLValueExpression :: Variable -> <ReadGraph> String
+    compileDocumentSCLHandlerValueExpression :: Variable -> <ReadGraph> String
 
     primitiveProperties :: <Proc> DocumentProperties
     
index 186edd25247fa9e67aa506404600cf18fb785ed6..d5a727ffae324f3219af714288bce219aa58f2ec 100644 (file)
@@ -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 "";
index 924c7c252b47a929183cfcb4403784486d5f1615..1da7fe6472ee78af0900d84d64f85ba3a9e5d312 100644 (file)
@@ -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
                                ));
        }
index 048e0840eaa55f07a79da6f82f6620d15b06957d..1c4b22ee0762cbc2f6f2a2b248d4b7d53e4ce895 100644 (file)
@@ -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);
index 869d5e32aada675fb56981116fd2eb8ac0961c56..0f7bff3969dbf649e2a4740de2c586312a80a0a2 100644 (file)
@@ -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.<PropertyInfo>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.<CompiledExpression>instance());
+                                CompileProceduralSCLMonitorRequest.compileAndEvaluate(graph, context);
                             } else {
-                                //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph);
-                                //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.<CompiledExpression>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<Variable,Object> 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())
index 9b0980600990695e785e2d1040c58ae6e13f4a16..d3ab613557cc874858b40c36d76d4cf6555e57c3 100644 (file)
@@ -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;
     }
index 92c97b78766c2548f9ea10a3d334a1e4fa6b6972..8070ae35821de1999da64ef0638a9081764c1827 100644 (file)
@@ -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)
index ba78a35483dda0faa00c93b69d89880d97944071..7767b5d2056649fa758748bc3011c31755b3b415 100644 (file)
@@ -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");
index 56e8eb3b66cc0cecaed1d4aa647e57ee7d180b1c..621c97684b86348be9d5bd11f331c0185e0635df 100644 (file)
@@ -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);
             
index b450766a6a5893c62b864381e25212c88be7dac3..43f9b3385e7deebf816778d44feb16597d628cd1 100644 (file)
@@ -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 (file)
index 0000000..24f8b31
--- /dev/null
@@ -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<ProcessedDInstanceAst> 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<fieldCount;++i) {
+            Type type = constructor.parameterTypes[i];
+            hasAtLeastOneOptional |= isOptional[i] = type instanceof TApply
+                    && ((TApply)type).function == Types.MAYBE;
+        }
+
+        // Generate toJson
+        {
+            /* toJson GeographicalLocation { latitude, longitude } = JsonObject [
+             *     JsonField "latitude" (toJson latitude),
+             *     JsonField "longitude" (toJson longitude)
+             * ]
+             * toJson GeographicalLocation { latitude, longitude } = JsonObject $ filterJust [
+             *     Just (JsonField "latitude" (toJson latitude)),
+             *     map (JsonField "longitude" . toJson) longitude
+             * ]
+             */
+            FieldAssignment[] fieldAssignments = new FieldAssignment[fieldCount];
+            for(int i=0;i<fieldCount;++i)
+                fieldAssignments[i] = new FieldAssignment(fieldNames[i], null);
+            Expression lhs = new EApply(
+                    new EVar("toJson"),
+                    new ERecord(new EVar(constructorName), fieldAssignments)
+                    );
+            Expression componentsExpression;
+            if(hasAtLeastOneOptional) {
+                Expression[] components = new Expression[fieldCount];
+                for(int i=0;i<fieldCount;++i) {
+                    if(isOptional[i])
+                        components[i] = new EApply(new EConstant(map),
+                                new EApply(new EConstant(dot),
+                                        new EApply(new EConstant(JsonField), new ELiteral(new StringConstant(fieldNames[i]))),
+                                        new EConstant(toJson)
+                                        ),
+                                new EVar(fieldNames[i])
+                                );
+                    else
+                        components[i] = new EApply(new EConstant(Just),
+                                new EApply(new EConstant(JsonField),
+                                        new ELiteral(new StringConstant(fieldNames[i])),
+                                        new EApply(new EConstant(toJson), new EVar(fieldNames[i]))
+                                        ));
+                }
+                componentsExpression = new EApply(new EConstant(filterJust),
+                        new EListLiteral(components));
+            }
+            else {
+                Expression[] components = new Expression[fieldCount];
+                for(int i=0;i<fieldCount;++i) {
+                    components[i] = new EApply(new EConstant(JsonField),
+                            new ELiteral(new StringConstant(fieldNames[i])),
+                            new EApply(new EConstant(toJson), new EVar(fieldNames[i]))
+                            );
+                }
+                componentsExpression = new EListLiteral(components);
+            }
+            Expression rhs = new EApply(new EConstant(JsonObject), componentsExpression);
+            try {
+                DValueAst valueAst = new DValueAst(lhs, rhs);
+                valueAst.setLocationDeep(der.location);
+                valueDefs.add(valueAst);
+            } catch (NotPatternException e) {
+                errorLog.log(e.getExpression().location, "Not a pattern (a).");
+            }
+        }
+
+        // Generate fromJson
+        {
+            /* fromJson object = GeographicalLocation {
+             *     latitude = fromJson $ fromJust $ lookupJsonField "latitude" object,
+             *     longitude = map fromJson $ lookupJsonField "longitude" object
+             * }
+             */
+            Expression lhs = new EApply(
+                    new EVar("fromJson"),
+                    new EVar("jsonObject")
+                    );
+            FieldAssignment[] fieldAssignments = new FieldAssignment[fieldCount];
+            for(int i=0;i<fieldCount;++i) {
+                Expression fieldValue = new EApply(new EConstant(lookupJsonField),
+                        new ELiteral(new StringConstant(fieldNames[i])),
+                        new EVar("jsonObject")
+                        );
+                if(isOptional[i]) {
+                    fieldValue = new EApply(new EConstant(map), new EConstant(fromJson), fieldValue);
+                }
+                else {
+                    fieldValue = new EApply(new EConstant(fromJust), fieldValue);
+                    fieldValue = new EApply(new EConstant(fromJson), fieldValue);
+                }
+                fieldAssignments[i] = new FieldAssignment(fieldNames[i], fieldValue);
+            }
+            Expression rhs = new ERecord(new EVar(constructorName),
+                    fieldAssignments
+                    );
+            try {
+                DValueAst valueAst = new DValueAst(lhs, rhs);
+                valueAst.setLocationDeep(der.location);
+                valueDefs.add(valueAst);
+            } catch (NotPatternException e) {
+                errorLog.log(e.getExpression().location, "Not a pattern (b).");
+            }
+        }
+
+        instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
+    }
+
+}
index 659329df7ed8ad12f1b5cc293f85851a0db0ec1e..cacffb01acc806a48d284f220afc8e874c8b8a65 100644 (file)
@@ -1,3 +1,23 @@
+/*
+
+An example how to implement 
+
+data GeographicalLocation = GeographicalLocation {
+    latitude :: Double,
+    longitude :: Double
+}
+
+instance Json GeographicalLocation where
+    toJson GeographicalLocation { latitude, longitude } = JsonObject [
+        JsonField "latitude" (toJson latitude),
+        JsonField "longitude" (toJson longitude)
+    ]
+    fromJson object = GeographicalLocation {
+        latitude = fromJson $ fromJust $ lookupJsonField "latitude" object,
+        longitude = fromJson $ fromJust $ lookupJsonField "longitude" object
+    }
+*/
+
 import "StandardLibrary"
 import "Data/Writer"
 import "JavaBuiltin" as Java
@@ -154,6 +174,7 @@ instance Json Double where
     readJson = getDoubleValue
     toJson = JsonDouble
     fromJson (JsonDouble value) = value
+    fromJson (JsonLong value) = Java.l2d value
 
 instance Json Float where
     writeJson = writeNumberFloat
@@ -298,6 +319,12 @@ data Json =
   | JsonObject [JsonField]
 data JsonField = JsonField String Json
   
+lookupJsonField :: String -> 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
 
index 1b2096eb9c63932478c8e291bc442e7dd19986ba..9aa1f0dddc628a9c05f63934e7311d7158724c76 100644 (file)
@@ -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> T getAdapter(Class<T> adapter) {
+        if (IContentOutlinePage.class.equals(adapter)) {
+            return (T) outline;
+        }
+        return super.getAdapter(adapter);
+    }
+
     /**
      * Text navigation action to navigate to the next sub-word.
      *
index d333f235ad2bde17f68b12f6ce00f771bb31396f..80e34c3746565f70cdf625cfcde5b19e5e2326a9 100644 (file)
 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> 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<SCLValue> values = new ArrayList<>();
+            result.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, value -> {
+                values.add(value);
+            });
+            values.sort(new Comparator<SCLValue>() {
+
+                @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<TCon> types = new ArrayList<>();
+            result.findTypesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, type -> {
+                types.add(type);
+            });
+            types.sort(new Comparator<TCon>() {
+
+                @Override
+                public int compare(TCon o1, TCon o2) {
+                    return o1.name.compareTo(o2.name);
+                }
+            });
+            List<Object> 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);
+            }
+        }
     }
 }
index b2b4ea2ec3ac6fecd3b564779bebef1ce659df86..2552192ef75dfa1f45d215c99855b87e91555a7d 100644 (file)
@@ -124,7 +124,6 @@ public class Synchronizer {
            while((cur = cur.getCause()) != null) {
                if(!(cur instanceof MissingVariableValueException)) {
                    handler.reportProblem(cur.getMessage());
-                   break;
                }
            }
        } catch (Exception e) {
index 6e9975b68ef09d2207438b728011640fa2f9efdc..5e564cc9114943df427ee1a1bda6877926f335ef 100644 (file)
@@ -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);
         }