mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 481126 - Convert Acorn AST into Java
Added the class QmlASTNodeHandler that creates and manages Proxy instances of the QML AST node interfaces. The proxies are created dynamically based on what methods are called on the interface. That way, the AST is loaded as needed rather than all at once. Added a few tests to verify behavior (however, they are not comprehensive; there are a lot more cases that should be verified in the future). Change-Id: I64038f9668942a67e1f1b7dceac6c7dbed2d46d7 Signed-off-by: Matthew Bastien <mbastien@blackberry.com>
This commit is contained in:
parent
6266df700b
commit
a43976b882
20 changed files with 695 additions and 63 deletions
|
@ -1,34 +1,45 @@
|
|||
package org.eclipse.cdt.qt.core.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.QMLTernCompletion;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IJSBinaryExpression;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IJSBinaryExpression.BinaryOperator;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlASTNode;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlHeaderItem;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlImport;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlObjectMember;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlProgram;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlPropertyBinding;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlRootObject;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlScriptBinding;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public class NashornTests {
|
||||
|
||||
protected static QMLAnalyzer analyzer;
|
||||
protected static IQMLAnalyzer analyzer;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadAnalyzer() {
|
||||
analyzer = Activator.getService(QMLAnalyzer.class);
|
||||
analyzer = Activator.getService(IQMLAnalyzer.class);
|
||||
}
|
||||
|
||||
protected void getCompletions(String code, QMLTernCompletion... expected) throws Throwable {
|
||||
int pos = code.indexOf('|');
|
||||
code = code.substring(0, pos) + code.substring(pos + 1);
|
||||
|
||||
Collection<QMLTernCompletion> QMLTernCompletions = analyzer.getCompletions("test1.qml", code, pos);
|
||||
Collection<QMLTernCompletion> QMLTernCompletions = analyzer.getCompletions("test1.qml", code, pos, false);
|
||||
|
||||
Map<String, QMLTernCompletion> set = new HashMap<>();
|
||||
Set<String> unexpected = new HashSet<>();
|
||||
|
@ -55,7 +66,108 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test1() throws Throwable {
|
||||
public void testParseFile1() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseFile("main.qml", "");
|
||||
assertEquals("Unexpected program node type", "QMLProgram", node.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseFile2() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseFile("main.qml", "import QtQuick 2.2");
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
List<IQmlHeaderItem> headerItems = program.getHeaderItemList().getItems();
|
||||
assertEquals("Unexpected number of header items", 1, headerItems.size());
|
||||
assertThat(headerItems.get(0), instanceOf(IQmlImport.class));
|
||||
IQmlImport imp = (IQmlImport) headerItems.get(0);
|
||||
assertEquals("Unexpected module identifier", "QtQuick", imp.getModule().getIdentifier().getName());
|
||||
assertEquals("Unexpected module raw version", "2.2", imp.getModule().getVersion().getRaw());
|
||||
assertEquals("Unexpected module version", 2.2, imp.getModule().getVersion().getValue(), 0.0001d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString1() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("", "qml", true, true);
|
||||
assertEquals("Unexpected program node type", "QMLProgram", node.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString2() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("import QtQuick 2.2", "qml", true, true);
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
List<IQmlHeaderItem> headerItems = program.getHeaderItemList().getItems();
|
||||
assertEquals("Unexpected number of header items", 1, headerItems.size());
|
||||
assertThat(headerItems.get(0), instanceOf(IQmlImport.class));
|
||||
IQmlImport imp = (IQmlImport) headerItems.get(0);
|
||||
assertEquals("Unexpected module identifier", "QtQuick", imp.getModule().getIdentifier().getName());
|
||||
assertEquals("Unexpected module raw version", "2.2", imp.getModule().getVersion().getRaw());
|
||||
assertEquals("Unexpected module version", 2.2, imp.getModule().getVersion().getValue(), 0.0001d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString3() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("import QtQuick 2.2", "qml", true, true);
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
List<IQmlHeaderItem> headerItems = program.getHeaderItemList().getItems();
|
||||
assertEquals("Unexpected number of header items", 1, headerItems.size());
|
||||
assertThat(headerItems.get(0), instanceOf(IQmlImport.class));
|
||||
IQmlImport imp = (IQmlImport) headerItems.get(0);
|
||||
assertEquals("Unexpected start range", 0, imp.getRange()[0]);
|
||||
assertEquals("Unexpected end range", 18, imp.getRange()[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString4() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("import QtQuick 2.2", "qml", true, true);
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
List<IQmlHeaderItem> headerItems = program.getHeaderItemList().getItems();
|
||||
assertEquals("Unexpected number of header items", 1, headerItems.size());
|
||||
assertThat(headerItems.get(0), instanceOf(IQmlImport.class));
|
||||
IQmlImport imp = (IQmlImport) headerItems.get(0);
|
||||
assertEquals("Unexpected start line", 1, imp.getLocation().getStart().getLine());
|
||||
assertEquals("Unexpected start column", 0, imp.getLocation().getStart().getColumn());
|
||||
assertEquals("Unexpected start line", 1, imp.getLocation().getEnd().getLine());
|
||||
assertEquals("Unexpected start column", 18, imp.getLocation().getEnd().getColumn());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString5() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("QtObject {}", "qml", true, true);
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
List<IQmlHeaderItem> headerItems = program.getHeaderItemList().getItems();
|
||||
assertEquals("Unexpected number of header items", 0, headerItems.size());
|
||||
assertNotNull("Root object was null", program.getRootObject());
|
||||
IQmlRootObject root = program.getRootObject();
|
||||
assertEquals("Unexpected root object type", "QMLObjectDefinition", root.getType());
|
||||
assertEquals("Unexpected root object identifier", "QtObject", root.getIdentifier().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseString6() throws Throwable {
|
||||
IQmlASTNode node = analyzer.parseString("QtObject {s: 3 + 3}", "qml", true, true);
|
||||
assertThat(node, instanceOf(IQmlProgram.class));
|
||||
IQmlProgram program = (IQmlProgram) node;
|
||||
assertNotNull("Root object was null", program.getRootObject());
|
||||
IQmlRootObject root = program.getRootObject();
|
||||
List<IQmlObjectMember> members = root.getBody().getMembers();
|
||||
assertEquals("Unexpected number of root object members", 1, members.size());
|
||||
assertThat(members.get(0), instanceOf(IQmlPropertyBinding.class));
|
||||
IQmlPropertyBinding bind = (IQmlPropertyBinding) members.get(0);
|
||||
assertThat(bind.getBinding(), instanceOf(IQmlScriptBinding.class));
|
||||
IQmlScriptBinding scriptBinding = (IQmlScriptBinding) bind.getBinding();
|
||||
assertFalse("Script binding was not a JavaScript expression", scriptBinding.isBlock());
|
||||
assertThat(scriptBinding.getScript(), instanceOf(IJSBinaryExpression.class));
|
||||
assertEquals("Unexpected expression type", "BinaryExpression", scriptBinding.getScript().getType());
|
||||
IJSBinaryExpression expr = (IJSBinaryExpression) scriptBinding.getScript();
|
||||
assertEquals("Unexpected binary operator", BinaryOperator.Add, expr.getOperator());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompletions1() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -64,7 +176,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test2() throws Throwable {
|
||||
public void testCompletions2() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -75,7 +187,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test3() throws Throwable {
|
||||
public void testCompletions3() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -83,7 +195,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test4() throws Throwable {
|
||||
public void testCompletions4() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -118,7 +230,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test5() throws Throwable {
|
||||
public void testCompletions5() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +265,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test6() throws Throwable {
|
||||
public void testCompletions6() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -188,7 +300,7 @@ public class NashornTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test7() throws Throwable {
|
||||
public void testCompletions7() throws Throwable {
|
||||
if (analyzer == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -31,4 +31,5 @@ Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt.
|
|||
org.eclipse.cdt.internal.qt.core.qmldir;x-friends:="org.eclipse.cdt.qt.core.tests",
|
||||
org.eclipse.cdt.qt.core,
|
||||
org.eclipse.cdt.qt.core.location,
|
||||
org.eclipse.cdt.qt.core.qmldir
|
||||
org.eclipse.cdt.qt.core.qmldir,
|
||||
org.eclipse.cdt.qt.core.qmljs
|
||||
|
|
|
@ -623,6 +623,7 @@
|
|||
// replacing JavaScripts top-level. Here we are parsing such things
|
||||
// as the root object literal and header statements of QML. Eventually,
|
||||
// these rules will delegate down to JavaScript expressions.
|
||||
node.mode = this.options.mode;
|
||||
node.headerItemList = this.qml_parseHeaderItemList();
|
||||
node.rootObject = null;
|
||||
if (this.type !== tt.eof) {
|
||||
|
|
|
@ -656,6 +656,7 @@ var injectQMLLoose;
|
|||
// as the root object literal and header statements of QML. Eventually,
|
||||
// these rules will delegate down to JavaScript expressions.
|
||||
var node = this.startNode();
|
||||
node.mode = this.options.mode;
|
||||
node.headerItemList = this.qml_parseHeaderItemList();
|
||||
node.rootObject = null;
|
||||
if (this.tok.type !== tt.eof) {
|
||||
|
|
|
@ -13,8 +13,8 @@ import javax.script.ScriptException;
|
|||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationFactory;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQtInstallManager;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
@ -64,8 +64,8 @@ public class Activator extends Plugin {
|
|||
context.registerService(IQtInstallManager.class, new QtInstallManager(), null);
|
||||
|
||||
QMLAnalyzer qmlAnalyzer = new QMLAnalyzer();
|
||||
context.registerService(QMLAnalyzer.class, qmlAnalyzer, null);
|
||||
new Job("Load QML Analyzer") {
|
||||
context.registerService(IQMLAnalyzer.class, qmlAnalyzer, null);
|
||||
new Job("Load QML Analyzer") { //$NON-NLS-1$
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.qt.core;
|
||||
package org.eclipse.cdt.internal.qt.core;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -27,10 +27,12 @@ import javax.script.ScriptEngine;
|
|||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.QMLTernCompletion;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlASTNode;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public class QMLAnalyzer {
|
||||
public class QMLAnalyzer implements IQMLAnalyzer {
|
||||
|
||||
private ScriptEngine engine;
|
||||
private Invocable invoke;
|
||||
|
@ -72,6 +74,9 @@ public class QMLAnalyzer {
|
|||
ResolveDirectory resolveDirectory = (file, pathString) -> {
|
||||
String filename = (String) file.get("name");
|
||||
String fileDirectory = new File(filename).getParent();
|
||||
if (fileDirectory == null) {
|
||||
fileDirectory = "";
|
||||
}
|
||||
if (pathString == null) {
|
||||
return fixPathString(fileDirectory);
|
||||
}
|
||||
|
@ -130,43 +135,134 @@ public class QMLAnalyzer {
|
|||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFile(String fileName, String code) throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
invoke.invokeMethod(tern, "addFile", fixPathString(fileName), code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteFile(String fileName) throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
invoke.invokeMethod(tern, "delFile", fixPathString(fileName));
|
||||
}
|
||||
|
||||
private static class ASTCallback implements RequestCallback {
|
||||
private IQmlASTNode ast;
|
||||
|
||||
@Override
|
||||
public void callback(Object err, Object data) {
|
||||
if (err != null) {
|
||||
throw new RuntimeException(err.toString());
|
||||
} else {
|
||||
try {
|
||||
ast = QmlASTNodeHandler.createQmlASTProxy((Bindings) ((Bindings) data).get("ast"));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IQmlASTNode getAST() {
|
||||
return ast;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQmlASTNode parseFile(String fileName, String text) throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
fileName = fixPathString(fileName);
|
||||
|
||||
Bindings query = engine.createBindings();
|
||||
query.put("type", "parseFile");
|
||||
query.put("file", fileName);
|
||||
Bindings request = engine.createBindings();
|
||||
request.put("query", query);
|
||||
|
||||
if (text != null) {
|
||||
Bindings file = engine.createBindings();
|
||||
file.put("type", "full");
|
||||
file.put("name", fileName);
|
||||
file.put("text", text);
|
||||
Bindings files = (Bindings) engine.eval("new Array()");
|
||||
invoke.invokeMethod(files, "push", file);
|
||||
request.put("files", files);
|
||||
}
|
||||
|
||||
ASTCallback callback = new ASTCallback();
|
||||
invoke.invokeMethod(tern, "request", request, invoke.invokeFunction("requestCallback", callback));
|
||||
return callback.getAST();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQmlASTNode parseString(String text) throws NoSuchMethodException, ScriptException {
|
||||
return parseString(text, "qml", false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQmlASTNode parseString(String text, String mode, boolean locations, boolean ranges)
|
||||
throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
Bindings query = engine.createBindings();
|
||||
query.put("type", "parseString");
|
||||
query.put("text", text);
|
||||
Bindings options = engine.createBindings();
|
||||
options.put("mode", mode);
|
||||
options.put("locations", locations);
|
||||
options.put("ranges", ranges);
|
||||
query.put("options", options);
|
||||
Bindings request = engine.createBindings();
|
||||
request.put("query", query);
|
||||
|
||||
ASTCallback callback = new ASTCallback();
|
||||
invoke.invokeMethod(tern, "request", request, invoke.invokeFunction("requestCallback", callback));
|
||||
return callback.getAST();
|
||||
}
|
||||
|
||||
protected <T> T[] toJavaArray(Bindings binding, Class<T[]> clazz) throws NoSuchMethodException, ScriptException {
|
||||
return clazz.cast(invoke.invokeMethod(engine.get("Java"), "to", binding,
|
||||
clazz.getCanonicalName() + (clazz.isArray() ? "" : "[]")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QMLTernCompletion> getCompletions(String fileName, String text, int pos)
|
||||
throws NoSuchMethodException, ScriptException {
|
||||
return getCompletions(fileName, text, pos, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QMLTernCompletion> getCompletions(String fileName, String text, int pos, boolean includeKeywords)
|
||||
throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
fileName = fixPathString(fileName);
|
||||
Bindings file = engine.createBindings();
|
||||
file.put("type", "full");
|
||||
file.put("name", fileName);
|
||||
file.put("text", text);
|
||||
Bindings files = (Bindings) engine.eval("new Array()");
|
||||
invoke.invokeMethod(files, "push", file);
|
||||
|
||||
Bindings query = engine.createBindings();
|
||||
query.put("type", "completions");
|
||||
query.put("lineCharPositions", true);
|
||||
query.put("file", fileName);
|
||||
query.put("end", pos);
|
||||
query.put("types", true);
|
||||
query.put("docs", false);
|
||||
query.put("urls", false);
|
||||
query.put("origins", true);
|
||||
query.put("filter", true);
|
||||
query.put("caseInsensitive", true);
|
||||
query.put("lineCharPositions", true);
|
||||
query.put("expandWordForward", false);
|
||||
query.put("includeKeywords", true);
|
||||
query.put("guess", false);
|
||||
query.put("sort", true);
|
||||
query.put("expandWordForward", false);
|
||||
query.put("includeKeywords", includeKeywords);
|
||||
|
||||
Bindings request = engine.createBindings();
|
||||
request.put("files", files);
|
||||
request.put("query", query);
|
||||
if (text != null) {
|
||||
Bindings file = engine.createBindings();
|
||||
file.put("type", "full");
|
||||
file.put("name", fileName);
|
||||
file.put("text", text);
|
||||
Bindings files = (Bindings) engine.eval("new Array()");
|
||||
invoke.invokeMethod(files, "push", file);
|
||||
request.put("files", files);
|
||||
}
|
||||
|
||||
List<QMLTernCompletion> completions = new ArrayList<>();
|
||||
|
||||
|
@ -176,8 +272,7 @@ public class QMLAnalyzer {
|
|||
} else {
|
||||
try {
|
||||
Bindings comps = (Bindings) ((Bindings) data).get("completions");
|
||||
for (Bindings completion : (Bindings[]) invoke.invokeMethod(engine.get("Java"), "to", comps,
|
||||
"javax.script.Bindings[]")) {
|
||||
for (Bindings completion : toJavaArray(comps, Bindings[].class)) {
|
||||
completions.add(new QMLTernCompletion((String) completion.get("name"),
|
||||
(String) completion.get("type"), (String) completion.get("origin")));
|
||||
}
|
||||
|
@ -192,16 +287,11 @@ public class QMLAnalyzer {
|
|||
return completions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Bindings> getDefinition(String identifier, String fileName, String text, int pos)
|
||||
throws NoSuchMethodException, ScriptException {
|
||||
waitUntilLoaded();
|
||||
fileName = fixPathString(fileName);
|
||||
Bindings file = engine.createBindings();
|
||||
file.put("type", "full");
|
||||
file.put("name", fileName);
|
||||
file.put("text", text);
|
||||
Bindings files = (Bindings) engine.eval("new Array()");
|
||||
invoke.invokeMethod(files, "push", file);
|
||||
|
||||
Bindings query = engine.createBindings();
|
||||
query.put("type", "definition");
|
||||
|
@ -217,8 +307,16 @@ public class QMLAnalyzer {
|
|||
query.put("includeKeywords", true);
|
||||
query.put("guess", false);
|
||||
Bindings request = engine.createBindings();
|
||||
request.put("files", files);
|
||||
request.put("query", query);
|
||||
if (text != null) {
|
||||
Bindings file = engine.createBindings();
|
||||
file.put("type", "full");
|
||||
file.put("name", fileName);
|
||||
file.put("text", text);
|
||||
Bindings files = (Bindings) engine.eval("new Array()");
|
||||
invoke.invokeMethod(files, "push", file);
|
||||
request.put("files", files);
|
||||
}
|
||||
|
||||
List<Bindings> definitions = new ArrayList<>();
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.qt.core;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.script.Bindings;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.core.location.Position;
|
||||
import org.eclipse.cdt.internal.qt.core.location.SourceLocation;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.location.ISourceLocation;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IJSLiteral;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IJSRegExpLiteral;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlASTNode;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlObjectDefinition;
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlRootObject;
|
||||
|
||||
/**
|
||||
* Translates a JavaScript {@link Bindings} object into a QML AST. This class employs {@link java.lang.reflect.Proxy} in order to
|
||||
* dynamically create the AST at runtime.
|
||||
* <p>
|
||||
* To begin translation simply call the static method <code>createQmlASTProxy</code>. The AST is translated only when it needs to be
|
||||
* (i.e. when one of its 'get' methods are called).
|
||||
*/
|
||||
public class QmlASTNodeHandler implements InvocationHandler {
|
||||
private static final String NODE_QML_PREFIX = "QML"; //$NON-NLS-1$
|
||||
private static final String NODE_TYPE_PROPERTY = "type"; //$NON-NLS-1$
|
||||
private static final String NODE_REGEX_PROPERTY = "regex"; //$NON-NLS-1$
|
||||
private static final String CREATE_ENUM_METHOD = "fromObject"; //$NON-NLS-1$
|
||||
private static final String AST_PACKAGE = "org.eclipse.cdt.qt.core.qmljs."; //$NON-NLS-1$
|
||||
private static final String AST_QML_PREFIX = "IQml"; //$NON-NLS-1$
|
||||
private static final String AST_JS_PREFIX = "IJS"; //$NON-NLS-1$
|
||||
|
||||
private static String getPropertyName(String method) {
|
||||
String name = ""; //$NON-NLS-1$
|
||||
if (method.startsWith("is")) { //$NON-NLS-1$
|
||||
name = method.substring(2, 3).toLowerCase() + method.substring(3);
|
||||
} else if (method.startsWith("get")) { //$NON-NLS-1$
|
||||
name = method.substring(3, 4).toLowerCase() + method.substring(4);
|
||||
}
|
||||
if (name.equalsIgnoreCase("identifier")) { //$NON-NLS-1$
|
||||
return "id"; //$NON-NLS-1$
|
||||
} else if (name.equalsIgnoreCase("location")) { //$NON-NLS-1$
|
||||
return "loc"; //$NON-NLS-1$
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IQmlASTNode} from the given {@link Bindings}. This is a helper method equivalent to
|
||||
* <code>createQmlASTProxy(node, null)</code>
|
||||
*
|
||||
* @param node
|
||||
* the AST node as retrieved from Nashorn
|
||||
* @return a Proxy representing the given node
|
||||
* @throws ClassNotFoundException
|
||||
* if the node does not represent a valid QML AST Node
|
||||
* @see {@link QmlASTNodeHandler#createQmlASTProxy(Bindings, Class)}
|
||||
*/
|
||||
public static IQmlASTNode createQmlASTProxy(Bindings node) throws ClassNotFoundException {
|
||||
return createQmlASTProxy(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IQmlASTNode} from the given {@link Bindings}. If a return type is specified, it will take precedence
|
||||
* over the type retrieved from the binding. This is useful for nodes that extend, but do not add functionality to, an acorn AST
|
||||
* element. A good example of this is {@link IQmlRootObject} which extends {@link IQmlObjectDefinition}. We can easily determine
|
||||
* the location in the AST at which we want an IQmlRootObject over an IQmlObjectDefinition and set the returnType accordingly.
|
||||
*
|
||||
* @param node
|
||||
* the node as retrieved from acorn
|
||||
* @param returnType
|
||||
* the expected node to return or null
|
||||
* @return a Proxy representing the given node
|
||||
* @throws ClassNotFoundException
|
||||
* if the node does not represent a valid QML AST Node
|
||||
*/
|
||||
public static IQmlASTNode createQmlASTProxy(Bindings node, Class<?> returnType) throws ClassNotFoundException {
|
||||
String type = (String) node.getOrDefault(NODE_TYPE_PROPERTY, ""); //$NON-NLS-1$
|
||||
if (type.startsWith(NODE_QML_PREFIX)) {
|
||||
type = AST_QML_PREFIX + type.substring(3);
|
||||
} else {
|
||||
type = AST_JS_PREFIX + type;
|
||||
}
|
||||
Class<?> astClass = Class.forName(AST_PACKAGE + type);
|
||||
if (astClass.equals(IJSLiteral.class)) {
|
||||
// If this is a Literal, we have to distinguish it between a RegExp Literal using the 'regex' property
|
||||
if (node.get(NODE_REGEX_PROPERTY) != null) {
|
||||
astClass = IJSRegExpLiteral.class;
|
||||
}
|
||||
}
|
||||
if (returnType != null) {
|
||||
if (!IQmlASTNode.class.isAssignableFrom(astClass)) {
|
||||
throw new ClassCastException(astClass + " cannot be cast to " + IQmlASTNode.class); //$NON-NLS-1$
|
||||
}
|
||||
if (astClass.isAssignableFrom(returnType)) {
|
||||
astClass = returnType;
|
||||
}
|
||||
}
|
||||
return (IQmlASTNode) Proxy.newProxyInstance(QmlASTNodeHandler.class.getClassLoader(),
|
||||
new Class<?>[] { astClass },
|
||||
new QmlASTNodeHandler(node));
|
||||
}
|
||||
|
||||
private final QMLAnalyzer analyzer;
|
||||
private final Bindings node;
|
||||
private final Map<String, Object> methodResults;
|
||||
|
||||
private QmlASTNodeHandler(Bindings node) {
|
||||
this.analyzer = (QMLAnalyzer) Activator.getService(IQMLAnalyzer.class);
|
||||
this.node = node;
|
||||
this.methodResults = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String mName = method.getName();
|
||||
if (!methodResults.containsKey(method.getName())) {
|
||||
// Invoke the default implementation of the method if possible
|
||||
if (method.isDefault()) {
|
||||
final Class<?> declaringClass = method.getDeclaringClass();
|
||||
Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class,
|
||||
int.class);
|
||||
constructor.setAccessible(true);
|
||||
methodResults.put(mName, constructor.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
|
||||
.unreflectSpecial(method, declaringClass)
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args));
|
||||
} else {
|
||||
// Use the return type of the method as well as its contents of the node to get the Object to return
|
||||
String pName = getPropertyName(mName);
|
||||
methodResults.put(mName, handleObject(node.get(pName), method.getReturnType()));
|
||||
}
|
||||
}
|
||||
return methodResults.get(method.getName());
|
||||
}
|
||||
|
||||
private Object handleObject(Object value, Class<?> expectedType) throws Throwable {
|
||||
if (expectedType.isAssignableFrom(ISourceLocation.class)) {
|
||||
// ISourceLocation doesn't correspond to an AST Node and needs to be created manually from
|
||||
// the given Bindings.
|
||||
if (value instanceof Bindings) {
|
||||
Bindings bind = (Bindings) value;
|
||||
SourceLocation loc = new SourceLocation();
|
||||
loc.setSource((String) bind.get("source")); //$NON-NLS-1$
|
||||
Bindings start = (Bindings) bind.get("start"); //$NON-NLS-1$
|
||||
loc.setStart(new Position(((Number) start.get("line")).intValue(), //$NON-NLS-1$
|
||||
((Number) start.get("column")).intValue())); //$NON-NLS-1$
|
||||
Bindings end = (Bindings) bind.get("end"); //$NON-NLS-1$
|
||||
loc.setEnd(new Position(((Number) end.get("line")).intValue(), //$NON-NLS-1$
|
||||
((Number) end.get("column")).intValue())); //$NON-NLS-1$
|
||||
return loc;
|
||||
}
|
||||
return new SourceLocation();
|
||||
} else if (expectedType.isArray()) {
|
||||
Object arr = Array.newInstance(expectedType.getComponentType(), ((Bindings) value).size());
|
||||
int ctr = 0;
|
||||
for (Object obj : ((Bindings) value).values()) {
|
||||
Array.set(arr, ctr++, handleObject(obj, expectedType.getComponentType()));
|
||||
}
|
||||
return arr;
|
||||
} else if (expectedType.isAssignableFrom(List.class)) {
|
||||
if (value instanceof Bindings) {
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (Bindings object : analyzer.toJavaArray((Bindings) value, Bindings[].class)) {
|
||||
list.add(QmlASTNodeHandler.createQmlASTProxy(object));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
} else if (expectedType.isPrimitive()) {
|
||||
return handlePrimitive(value, expectedType);
|
||||
} else if (expectedType.isAssignableFrom(Number.class)) {
|
||||
if (value instanceof Number) {
|
||||
return value;
|
||||
}
|
||||
return new Integer(0);
|
||||
} else if (expectedType.isEnum()) {
|
||||
return expectedType.getMethod(CREATE_ENUM_METHOD, Object.class).invoke(null, value);
|
||||
} else if (value instanceof Bindings) {
|
||||
return QmlASTNodeHandler.createQmlASTProxy((Bindings) value, expectedType);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private Object handlePrimitive(Object value, Class<?> expectedType) throws Throwable {
|
||||
if (expectedType.isPrimitive()) {
|
||||
if (expectedType.equals(Boolean.TYPE)) {
|
||||
if (value instanceof Boolean) {
|
||||
return value;
|
||||
}
|
||||
return false;
|
||||
} else if (expectedType.equals(Character.TYPE)) {
|
||||
if (value instanceof Character) {
|
||||
return value;
|
||||
}
|
||||
return '\0';
|
||||
} else if (expectedType.equals(Byte.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).byteValue();
|
||||
}
|
||||
return (byte) 0;
|
||||
} else if (expectedType.equals(Short.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).shortValue();
|
||||
}
|
||||
return (short) 0;
|
||||
} else if (expectedType.equals(Integer.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
return 0;
|
||||
} else if (expectedType.equals(Long.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).longValue();
|
||||
}
|
||||
return 0l;
|
||||
} else if (expectedType.equals(Float.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).floatValue();
|
||||
}
|
||||
return 0.0f;
|
||||
} else if (expectedType.equals(Double.TYPE)) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).doubleValue();
|
||||
}
|
||||
return 0.0d;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("expectedType was not a primitive type"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.qt.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.qt.core.qmljs.IQmlASTNode;
|
||||
|
||||
public interface IQMLAnalyzer {
|
||||
|
||||
void addFile(String fileName, String code) throws NoSuchMethodException, ScriptException;
|
||||
|
||||
void deleteFile(String fileName) throws NoSuchMethodException, ScriptException;
|
||||
|
||||
IQmlASTNode parseFile(String fileName, String text) throws NoSuchMethodException, ScriptException;
|
||||
|
||||
IQmlASTNode parseString(String text) throws NoSuchMethodException, ScriptException;
|
||||
|
||||
IQmlASTNode parseString(String text, String mode, boolean locations, boolean ranges)
|
||||
throws NoSuchMethodException, ScriptException;
|
||||
|
||||
Collection<QMLTernCompletion> getCompletions(String fileName, String text, int pos)
|
||||
throws NoSuchMethodException, ScriptException;
|
||||
|
||||
Collection<QMLTernCompletion> getCompletions(String fileName, String text, int pos, boolean includeKeywords)
|
||||
throws NoSuchMethodException, ScriptException;
|
||||
|
||||
List<Bindings> getDefinition(String identifier, String fileName, String text, int pos)
|
||||
throws NoSuchMethodException, ScriptException;
|
||||
|
||||
void load() throws ScriptException, IOException, NoSuchMethodException;
|
||||
|
||||
}
|
|
@ -32,6 +32,17 @@ public interface IJSAssignmentExpression extends IJSExpression {
|
|||
AssignExclusiveOr("^"), //$NON-NLS-1$
|
||||
AssignAnd("&="); //$NON-NLS-1$
|
||||
|
||||
public static AssignmentOperator fromObject(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
for (AssignmentOperator op : AssignmentOperator.values()) {
|
||||
if (obj.equals(op.toString())) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String op;
|
||||
|
||||
private AssignmentOperator(String op) {
|
||||
|
|
|
@ -40,6 +40,17 @@ public interface IJSBinaryExpression extends IJSExpression {
|
|||
In("in"), //$NON-NLS-1$
|
||||
Instanceof("instanceof"); //$NON-NLS-1$
|
||||
|
||||
public static BinaryOperator fromObject(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
for (BinaryOperator op : BinaryOperator.values()) {
|
||||
if (obj.equals(op.toString())) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String op;
|
||||
|
||||
private BinaryOperator(String op) {
|
||||
|
@ -54,7 +65,7 @@ public interface IJSBinaryExpression extends IJSExpression {
|
|||
|
||||
@Override
|
||||
default String getType() {
|
||||
return "UnaryExpression"; //$NON-NLS-1$
|
||||
return "BinaryExpression"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public BinaryOperator getOperator();
|
||||
|
|
|
@ -22,6 +22,17 @@ public interface IJSLogicalExpression extends IJSExpression {
|
|||
Or("||"), //$NON-NLS-1$
|
||||
And("&&"); //$NON-NLS-1$
|
||||
|
||||
public static LogicalOperator fromObject(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
for (LogicalOperator op : LogicalOperator.values()) {
|
||||
if (obj.equals(op.toString())) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String op;
|
||||
|
||||
private LogicalOperator(String op) {
|
||||
|
|
|
@ -27,6 +27,17 @@ public interface IJSUnaryExpression extends IJSExpression {
|
|||
Void("void"), //$NON-NLS-1$
|
||||
Delete("delete"); //$NON-NLS-1$
|
||||
|
||||
public static UnaryOperator fromObject(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
for (UnaryOperator op : UnaryOperator.values()) {
|
||||
if (obj.equals(op.toString())) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String op;
|
||||
|
||||
private UnaryOperator(String op) {
|
||||
|
|
|
@ -22,6 +22,17 @@ public interface IJSUpdateExpression extends IQmlASTNode {
|
|||
Decrement("--"), //$NON-NLS-1$
|
||||
Increment("++"); //$NON-NLS-1$
|
||||
|
||||
public static UpdateOperator fromObject(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
for (UpdateOperator op : UpdateOperator.values()) {
|
||||
if (obj.equals(op.toString())) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String op;
|
||||
|
||||
private UpdateOperator(String op) {
|
||||
|
|
|
@ -969,20 +969,20 @@
|
|||
if (query.file) {
|
||||
// Get the file's AST. It should have been parsed already by the server.
|
||||
ast = file.ast;
|
||||
} else if (query.text) {
|
||||
} else {
|
||||
// Parse the file manually and get the AST.
|
||||
var text = query.text;
|
||||
var options = query.options || {
|
||||
var options = {
|
||||
directSourceFile: file,
|
||||
allowReturnOutsideFunction: true,
|
||||
allowImportExportEverywhere: true,
|
||||
ecmaVersion: srv.options.ecmaVersion
|
||||
};
|
||||
srv.signalReturnFirst("preParse", text, options);
|
||||
try {
|
||||
ast = acorn.parse(text, options);
|
||||
} catch (e) {
|
||||
ast = acorn.parse_dammit(text, options);
|
||||
for (var opt in query.options) {
|
||||
options[opt] = query.options[opt];
|
||||
}
|
||||
query.text = query.text || "";
|
||||
var text = srv.signalReturnFirst("preParse", query.text, options) || query.text;
|
||||
ast = infer.parse(text, options);
|
||||
srv.signal("postParse", ast, text);
|
||||
}
|
||||
return {
|
||||
|
|
|
@ -29,7 +29,7 @@ test("{Parse existing file}", function (server, callback, name) {
|
|||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast && resp.ast.type === "QMLProgram") {
|
||||
if (!resp.ast || resp.ast.type !== "QMLProgram") {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
}
|
||||
return callback("ok", name);
|
||||
|
@ -53,14 +53,33 @@ test("{Parse given file}", function (server, callback, name) {
|
|||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast && resp.ast.type === "QMLProgram") {
|
||||
if (!resp.ast || resp.ast.type !== "QMLProgram") {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
}
|
||||
return callback("ok", name);
|
||||
});
|
||||
});
|
||||
|
||||
test("{Parse text}", function (server, callback, name) {
|
||||
test("{Parse empty text}", function (server, callback, name) {
|
||||
server.request({
|
||||
query: {
|
||||
type: "parseString",
|
||||
text: ""
|
||||
}
|
||||
}, function (err, resp) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast) {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
} else if (resp.ast.type !== "QMLProgram" || resp.ast.mode !== "qml") {
|
||||
return callback("fail", name, "AST was not a QMLProgram with mode 'qml'");
|
||||
}
|
||||
return callback("ok", name);
|
||||
});
|
||||
});
|
||||
|
||||
test("{Parse text no mode}", function (server, callback, name) {
|
||||
server.request({
|
||||
query: {
|
||||
type: "parseString",
|
||||
|
@ -70,8 +89,57 @@ test("{Parse text}", function (server, callback, name) {
|
|||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast && resp.ast.type === "QMLProgram") {
|
||||
if (!resp.ast) {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
} else if (resp.ast.type !== "QMLProgram" || resp.ast.mode !== "qml") {
|
||||
return callback("fail", name, "AST was not a QMLProgram with mode 'qml'");
|
||||
}
|
||||
return callback("ok", name);
|
||||
});
|
||||
});
|
||||
|
||||
test("{Parse text (mode: qmltypes)}", function (server, callback, name) {
|
||||
server.request({
|
||||
query: {
|
||||
type: "parseString",
|
||||
text: "QtObject {\n\tobj: {\n\t\tprop1: 1,\n\t\tprop2: 2\n\t}\n}",
|
||||
options: {
|
||||
mode: "qmltypes"
|
||||
}
|
||||
}
|
||||
}, function (err, resp) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast) {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
} else if (resp.ast.type !== "QMLProgram" || resp.ast.mode !== "qmltypes") {
|
||||
return callback("fail", name, "AST was not a QMLProgram with mode 'qmltypes'");
|
||||
}
|
||||
return callback("ok", name);
|
||||
});
|
||||
});
|
||||
|
||||
test("{Parse text with locations}", function (server, callback, name) {
|
||||
server.request({
|
||||
query: {
|
||||
type: "parseString",
|
||||
text: "var w = 3",
|
||||
options: {
|
||||
mode: "js",
|
||||
locations: true
|
||||
}
|
||||
}
|
||||
}, function (err, resp) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!resp.ast) {
|
||||
return callback("fail", name, "AST could not be found in response");
|
||||
} else if (resp.ast.type !== "Program") {
|
||||
return callback("fail", name, "AST was not a JavaScript Program");
|
||||
} else if (!resp.ast.loc) {
|
||||
return callback("fail", name, "AST had no loc object");
|
||||
}
|
||||
return callback("ok", name);
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.Collection;
|
|||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.ui.Activator;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.QMLTernCompletion;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
|
@ -29,7 +29,7 @@ public class QMLContentAssistProcessor implements IContentAssistProcessor {
|
|||
private static final IContextInformation[] NO_CONTEXTS = {};
|
||||
private static final ICompletionProposal[] NO_COMPLETIONS = {};
|
||||
|
||||
private final QMLAnalyzer analyzer = Activator.getService(QMLAnalyzer.class);
|
||||
private final IQMLAnalyzer analyzer = Activator.getService(IQMLAnalyzer.class);
|
||||
private final QMLEditor editor;
|
||||
|
||||
public QMLContentAssistProcessor(QMLEditor editor) {
|
||||
|
|
|
@ -16,7 +16,7 @@ import javax.script.ScriptException;
|
|||
|
||||
import org.eclipse.cdt.internal.qt.ui.Activator;
|
||||
import org.eclipse.cdt.internal.qt.ui.actions.OpenDeclarationsAction;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
|
@ -41,7 +41,7 @@ public class QMLEditor extends TextEditor {
|
|||
private static final String BRACKET_MATCHING_PREFERENCE = "org.eclipse.cdt.qt.ui.qmlMatchingBrackets"; //$NON-NLS-1$
|
||||
|
||||
private static final char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
|
||||
private final QMLAnalyzer analyzer = Activator.getService(QMLAnalyzer.class);
|
||||
private final IQMLAnalyzer analyzer = Activator.getService(IQMLAnalyzer.class);
|
||||
|
||||
@Override
|
||||
protected void initializeEditor() {
|
||||
|
|
|
@ -14,7 +14,7 @@ import javax.script.Bindings;
|
|||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
|
@ -57,7 +57,7 @@ public class QMLHyperlink implements IHyperlink {
|
|||
|
||||
@Override
|
||||
public void open() {
|
||||
QMLAnalyzer analyzer = Activator.getService(QMLAnalyzer.class);
|
||||
IQMLAnalyzer analyzer = Activator.getService(IQMLAnalyzer.class);
|
||||
try {
|
||||
IDocument document = viewer.getDocument();
|
||||
String selected = document.get(region.getOffset(), region.getLength());
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
|||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.ui.Activator;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IResourceDelta;
|
||||
|
@ -30,7 +30,7 @@ import org.eclipse.core.runtime.jobs.Job;
|
|||
public class QMLTernFileUpdateJob extends Job {
|
||||
|
||||
private List<IResourceDelta> deltaList;
|
||||
private final QMLAnalyzer analyzer = Activator.getService(QMLAnalyzer.class);
|
||||
private final IQMLAnalyzer analyzer = Activator.getService(IQMLAnalyzer.class);
|
||||
|
||||
public QMLTernFileUpdateJob(List<IResourceDelta> deltas) {
|
||||
super("Add/Remove Files in Tern"); //$NON-NLS-1$
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.io.IOException;
|
|||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||
import org.eclipse.cdt.qt.core.QMLAnalyzer;
|
||||
import org.eclipse.cdt.qt.core.IQMLAnalyzer;
|
||||
import org.eclipse.core.commands.AbstractHandler;
|
||||
import org.eclipse.core.commands.ExecutionEvent;
|
||||
import org.eclipse.core.commands.ExecutionException;
|
||||
|
@ -23,7 +23,7 @@ import org.eclipse.core.runtime.jobs.Job;
|
|||
|
||||
/**
|
||||
* Our sample handler extends AbstractHandler, an IHandler base class.
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.core.commands.IHandler
|
||||
* @see org.eclipse.core.commands.AbstractHandler
|
||||
*/
|
||||
|
@ -35,7 +35,7 @@ public class ReloadAnalyzerHandler extends AbstractHandler {
|
|||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
Activator.getService(QMLAnalyzer.class).load();
|
||||
Activator.getService(IQMLAnalyzer.class).load();
|
||||
} catch (NoSuchMethodException | ScriptException | IOException e) {
|
||||
return Activator.error("Reloading QML Analyzer", e);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue