From 4474134a68589b5c3839aa7e36fee392a6b66742 Mon Sep 17 00:00:00 2001 From: Frédéric Jouault Date: Fri, 27 Mar 2015 08:14:03 +0100 Subject: added support for "parent context" navigation for autoCreate, octal escape sequences, and improved completion (notably by partially unescaping when necessary) --- .../org/eclipse/gmt/tcs/injector/TCSRuntime.java | 50 ++++++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/plugins/org.eclipse.gmt.tcs.injector/src/org/eclipse/gmt/tcs/injector/TCSRuntime.java b/plugins/org.eclipse.gmt.tcs.injector/src/org/eclipse/gmt/tcs/injector/TCSRuntime.java index 68e66a2..1526a2e 100644 --- a/plugins/org.eclipse.gmt.tcs.injector/src/org/eclipse/gmt/tcs/injector/TCSRuntime.java +++ b/plugins/org.eclipse.gmt.tcs.injector/src/org/eclipse/gmt/tcs/injector/TCSRuntime.java @@ -52,7 +52,8 @@ public class TCSRuntime { private boolean lastWasCreation; private List refSettings; private Object lastToken; - private CompletionInformation completionInformation = null; + // We use ATL's CompletionInformation so that other plugins using it are compatible. + private org.eclipse.m2m.atl.dsls.tcs.injector.CompletionInformation completionInformation = null; private int nbErrors = 0; @@ -65,7 +66,7 @@ public class TCSRuntime { this.keepNL = ("true".equals(arguments.get("keepNL"))) ? true : false; this.keepLocation = ("false".equals(arguments.get("keepLocation"))) ? false : true; this.keepComments = ("false".equals(arguments.get("keepComments"))) ? false : true; - this.completionInformation = (CompletionInformation)arguments.get("completionInformation"); + this.completionInformation = (org.eclipse.m2m.atl.dsls.tcs.injector.CompletionInformation)arguments.get("completionInformation"); // hyperlinks can be null this.hyperlinks = (Map)arguments.get("hyperlinks"); @@ -153,8 +154,16 @@ public class TCSRuntime { parserWrapper.setCommentsAfter(ame, token); } + private Map parent = new HashMap(); + public void set(Object ame, String prop, Object value) { getTargetModelAdapter().set(ame, prop, value); + + // the following works because set(...) should only be called for container references + if(getTargetModelAdapter().isAModelElement(value)) { + parent.put(value, ame); + } + if(trace != null) { ElementTrace et = (ElementTrace)trace.get(ame); if(et == null) { @@ -172,8 +181,17 @@ public class TCSRuntime { (offset >= parserWrapper.getStartOffset(lastToken) - 1) && (offset <= parserWrapper.getEndOffset(lastToken))) { if(completionInformation.getProposals().isEmpty()) { // only add the first (and therefore inner-most) + String token = (String)value; + // TODO: add parwerWrapper.getText instead of regexing + lastToken.toString().replaceAll("^.*='([^']*)'.*$", "$1"); + int tokenLength = parserWrapper.getEndOffset(lastToken) - parserWrapper.getStartOffset(lastToken) + 1; + if(tokenLength == token.length() + 2) { + // unescaping (but only works if no escaped character in the token) + // TODO: fix this hack + token = "\"" + token + "\""; + } completionInformation.getProposals().add(new Object[] {ame, prop, - ((String)value).substring(0, offset - parserWrapper.getStartOffset(lastToken) + 1) + token.substring(0, offset - parserWrapper.getStartOffset(lastToken) + 1) }); } } @@ -545,6 +563,11 @@ public class TCSRuntime { for(int i = 0 ; (i < path.length - (navigateLast ? 0 : 1)) && (ret != null) ; i++) { if(path[i].equals("#context")) { ret = currentContext.getElement(); + } else if(path[i].startsWith("#")) { // TODO: change # (e.g., to %) to avoid conflicts with #context? + String typeName = path[i].substring(1); + while(ret != null && !getTargetModelAdapter().isCandidate(ret, typeName)) { + ret = parent.get(ret); + } } else { Object v = getTargetModelAdapter().get(ret, path[i]); if(getTargetModelAdapter().isAModelElement(v)) { @@ -623,6 +646,10 @@ public class TCSRuntime { } } + public boolean canAutoCreate() { + return !this.autoCreate.equals("never"); + } + private Context currentContext; private Object object; private String propertyName; @@ -689,7 +716,22 @@ public class TCSRuntime { case '1': case '2': case '3': - throw new RuntimeException("octal escape sequences not supported yet"); + String v = "" + c; + c = ci.next(); + if(c >= '0' & c <= '9') { + v += c; + c = ci.next(); + if(c >= '0' & c <= '9') { + v += c; + } else { + ci.previous(); + } + } else { + ci.previous(); + } + tc = (char)(Integer.parseInt(v)); + break; + //throw new RuntimeException("octal escape sequences not supported yet"); default: throw new RuntimeException("unknown escape sequence: '\\" + c + "'"); } -- cgit v1.2.3