diff --git a/qt/org.eclipse.cdt.qt.core.acorn/.classpath b/qt/org.eclipse.cdt.qt.core.acorn/.classpath
deleted file mode 100644
index b862a296d38..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/.project b/qt/org.eclipse.cdt.qt.core.acorn/.project
deleted file mode 100644
index e8454d75162..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- org.eclipse.cdt.qt.core.acorn
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.pde.ManifestBuilder
-
-
-
-
- org.eclipse.pde.SchemaBuilder
-
-
-
-
-
- org.eclipse.pde.PluginNature
- org.eclipse.jdt.core.javanature
-
-
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/.settings/org.eclipse.jdt.core.prefs b/qt/org.eclipse.cdt.qt.core.acorn/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 295926d9641..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,7 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.8
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core.acorn/META-INF/MANIFEST.MF
deleted file mode 100644
index 0cb06697864..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,10 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: %pluginName
-Bundle-SymbolicName: org.eclipse.cdt.qt.core.acorn
-Bundle-Version: 2.0.0.qualifier
-Bundle-Activator: org.eclipse.cdt.qt.core.acorn.Activator
-Bundle-Vendor: %providerName
-Require-Bundle: org.eclipse.core.runtime
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Bundle-ActivationPolicy: lazy
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/inject.js b/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/inject.js
deleted file mode 100644
index 2d9dd903790..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/inject.js
+++ /dev/null
@@ -1,518 +0,0 @@
-/*******************************************************************************
- * 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
- *******************************************************************************/
-'use strict';
-
-module.exports = function(acorn) {
- // Acorn token types
- var tt = acorn.tokTypes;
-
- // QML token types
- var qtt = {};
- var keywords = {};
-
- /*
- * Shorthand for defining keywords in the 'keywords' variable with the following
- * format:
- * keywords[name].isPrimitive : if this is a primitive type
- * keywords[name].isQMLContextual : if this is a contextual keyword for QML
- *
- * Also stores the token's name in qtt._ for easy referencing later. None
- * of these keywords will be tokenized and, as such, are allowed to be used in
- * JavaScript expressions by acorn. The 'isQMLContextual' boolean in keywords refers
- * to those contextual keywords that are also contextual in QML's parser rules such
- * as 'color', 'list', 'alias', etc.
- */
- function kw(name, options) {
- if (options === undefined)
- options = {};
- qtt["_" + name] = name;
- keywords[name] = {};
- keywords[name].isPrimitive = options.isPrimitive ? true : false;
- keywords[name].isQMLContextual = options.isQMLContextual ? true : false;
- }
-
- // QML keywords
- kw("import");
- kw("pragma");
- kw("property", { isQMLContextual : true });
- kw("readonly", { isQMLContextual : true });
- kw("signal", { isQMLContextual : true });
- kw("as");
- kw("boolean", { isPrimitive: true });
- kw("double", { isPrimitive: true });
- kw("int", { isPrimitive: true });
- kw("alias", { isQMLContextual: true });
- kw("list", { isPrimitive: true, isQMLContextual: true });
- kw("color", { isPrimitive: true, isQMLContextual: true });
- kw("real", { isPrimitive: true, isQMLContextual: true });
- kw("string", { isPrimitive: true, isQMLContextual: true });
- kw("url", { isPrimitive: true, isQMLContextual: true });
-
- // Future reserved words
- kw("transient");
- kw("synchronized");
- kw("abstract");
- kw("volatile");
- kw("native");
- kw("goto");
- kw("byte");
- kw("long");
- kw("char");
- kw("short");
- kw("float");
-
- // QML parser methods
- var pp = acorn.Parser.prototype;
-
- /*
- * Parses a set of QML Header Statements which can either be of
- * the type import or pragma
- */
- pp.qml_parseHeaderStatements = function() {
- var node = this.startNode()
- node.statements = [];
-
- var loop = true;
- while (loop) {
- if (this.type === tt._import || this.isContextual(qtt._import)) {
- var qmlImport = this.qml_parseImportStatement();
- node.statements.push(qmlImport);
- } else if (this.isContextual(qtt._pragma)) {
- var qmlPragma = this.qml_parsePragmaStatement();
- node.statements.push(qmlPragma);
- } else {
- loop = false;
- }
- }
-
- if (node.statements.length > 0) {
- return this.finishNode(node, "QMLHeaderStatements");
- }
- return undefined;
- }
-
- /*
- * Parses a QML Pragma statement of the form:
- * 'pragma'
- */
- pp.qml_parsePragmaStatement = function() {
- var node = this.startNode();
- this.next();
- node.identifier = this.parseIdent(false);
- this.semicolon();
- return this.finishNode(node, "QMLPragmaStatement");
- }
-
- /*
- * Parses a QML Import statement of the form:
- * 'import' [as ]
- * 'import' [as ]
- *
- * as specified by http://doc.qt.io/qt-5/qtqml-syntax-imports.html
- */
- pp.qml_parseImportStatement = function() {
- var node = this.startNode();
- this.next();
-
- // The type of import varies solely on the next token
- switch(this.type) {
- case tt.name:
- node.module = this.qml_parseModule();
- break;
- case tt.string:
- node.directoryPath = this.parseLiteral(this.value);
- break;
- default:
- this.unexpected();
- break;
- }
-
- // Parse the qualifier, if any
- if (this.isContextual(qtt._as)) {
- node.qualifier = this.qml_parseQualifier();
- }
-
- this.semicolon();
- return this.finishNode(node, "QMLImportStatement");
- };
-
- /*
- * Parses a QML Module of the form:
- *
- */
- pp.qml_parseModule = function() {
- var node = this.startNode();
-
- node.qualifiedId = this.qml_parseQualifiedId();
- if (this.type === tt.num) {
- node.version = this.qml_parseVersionLiteral();
- } else {
- this.unexpected();
- }
-
- return this.finishNode(node, "QMLModule");
- };
-
- /*
- * Parses a QML Version Literal which consists of a major and minor
- * version separated by a '.'
- */
- pp.qml_parseVersionLiteral = function() {
- var node = this.startNode();
-
- node.raw = this.input.slice(this.start, this.end);
- node.value = this.value;
- var matches;
- if (matches = /(\d+)\.(\d+)/.exec(node.raw)) {
- node.major = parseInt(matches[1]);
- node.minor = parseInt(matches[2]);
- } else {
- this.raise(this.start, "QML module must specify major and minor version");
- }
-
- this.next();
- return this.finishNode(node, "QMLVersionLiteral");
- }
-
- /*
- * Parses a QML Qualifier of the form:
- * 'as'
- */
- pp.qml_parseQualifier = function() {
- var node = this.startNode();
- this.next();
- node.identifier = this.qml_parseIdent(false);
- return this.finishNode(node, "QMLQualifier");
- }
-
- /*
- * Parses a QML Object Literal of the form:
- * { ()* }
- *
- * http://doc.qt.io/qt-5/qtqml-syntax-basics.html#object-declarations
- */
- pp.qml_parseObjectLiteral = function(node) {
- if (!node) {
- node = this.startNode();
- }
- if (!node.qualifiedId) {
- node.qualifiedId = this.qml_parseQualifiedId();
- }
- node.block = this.qml_parseMemberBlock();
- return this.finishNode(node, "QMLObjectLiteral");
- }
-
- /*
- * Parses a QML Member Block of the form:
- * { * }
- */
- pp.qml_parseMemberBlock = function() {
- var node = this.startNode();
- this.expect(tt.braceL);
- node.members = [];
- while (!this.eat(tt.braceR)) {
- node.members.push(this.qml_parseMember());
- }
- return this.finishNode(node, "QMLMemberBlock");
- }
-
- /*
- * Parses a QML Member which can be one of the following:
- * - a QML Property Binding
- * - a Property Declaration (or Alias)
- * - a QML Object Literal
- * - a JavaScript Function Declaration
- * - a Signal Definition
- */
- pp.qml_parseMember = function() {
- var node = this.startNode();
-
- if (this.type === tt._default
- || this.isContextual(qtt._default)
- || this.isContextual(qtt._readonly)
- || this.isContextual(qtt._property)) {
- return this.qml_parsePropertyDeclaration(node);
- } else if (this.isContextual(qtt._signal)) {
- return this.qml_parseSignalDefinition(node);
- } else if (this.type === tt._function) {
- return this.parseFunctionStatement(node);
- }
-
- node.qualifiedId = this.qml_parseQualifiedId();
- switch(this.type) {
- case tt.braceL:
- return this.qml_parseObjectLiteral(node);
- case tt.colon:
- return this.qml_parseProperty(node);
- }
-
- this.unexpected();
- }
-
- /*
- * Parses a QML Property of the form:
- *
- */
- pp.qml_parseProperty = function(node) {
- if (!node) {
- node = this.startNode();
- }
- if (!node.qualifiedId) {
- node.qualifiedId = this.qml_parseQualifiedId();
- }
- node.binding = this.qml_parseBinding();
- return this.finishNode(node, "QMLProperty");
- }
-
- /*
- * Parses a QML Signal Definition of the form:
- * 'signal' [( [',' ]* )]?
- */
- pp.qml_parseSignalDefinition = function(node) {
- if (!node) {
- node = this.startNode();
- }
- this.next();
- node.identifier = this.qml_parseIdent(false);
- node.parameters = [];
- if (this.type === tt.parenL) {
- this.next();
- if (this.type !== tt.parenR) {
- do {
- var paramNode = this.startNode();
- paramNode.type = this.qml_parseIdent(false);
- paramNode.identifier = this.qml_parseIdent(false);
- node.parameters.push(paramNode);
- } while(this.eat(tt.comma));
- }
- if (!this.eat(tt.parenR)) {
- this.unexpected();
- }
- }
- this.semicolon();
- return this.finishNode(node, "QMLSignalDefinition");
- }
-
- /*
- * Parses a QML Property Declaration (or Alias) of the form:
- * ['default'|'readonly'] 'property' []
- */
- pp.qml_parsePropertyDeclaration = function(node) {
- node["default"] = false;
- node["readonly"] = false;
-
- if (this.type === tt._default || this.isContextual(qtt._default)) {
- node["default"] = true;
- this.next();
- } else if (this.eatContextual(qtt._readonly)) {
- node["readonly"] = true;
- }
- this.expectContextual(qtt._property);
- node.typeInfo = this.qml_parseType();
- node.identifier = this.qml_parseIdent(false);
- if (this.type !== tt.colon) {
- this.semicolon();
- } else {
- node.binding = this.qml_parseBinding();
- }
-
- if (node.typeInfo.type === qtt._alias) {
- node.typeInfo = undefined;
- return this.finishNode(node, "QMLPropertyAlias");
- }
- return this.finishNode(node, "QMLPropertyDeclaration");
- }
-
- /*
- * Parses a QML Binding of the form:
- * ':' (|)
- */
- pp.qml_parseBinding = function() {
- var node = this.startNode();
- this.expect(tt.colon);
-
- // TODO: solve ambiguity where a QML Object Literal starts with a
- // Qualified Id that looks very similar to a MemberExpression in
- // JavaScript. For now, we just won't parse statements like:
- // test: QMLObject { }
- // test: QMLObject.QualifiedId { }
-
- if (this.type === tt.braceL) {
- node.block = this.qml_parseStatementBlock();
- return this.finishNode(node, "QMLBinding");
- }
- node.expr = this.parseExpression(false);
- this.semicolon();
- return this.finishNode(node, "QMLBinding");
- }
-
- /*
- * Parses a QML Statement Block of the form:
- * { * }
- */
- pp.qml_parseStatementBlock = function() {
- var node = this.startNode();
- this.expect(tt.braceL);
- node.statements = [];
- while(!this.eat(tt.braceR)) {
- node.statements.push(this.parseStatement(true, false));
- }
- return this.finishNode(node, "QMLStatementBlock");
- }
-
- /*
- * Parses a QML Type which can be either a Qualified ID or a primitive type keyword.
- * Returns a node of type qtt._alias if the type keyword parsed was "alias".
- */
- pp.qml_parseType = function() {
- var node = this.startNode();
-
- if (this.type === tt.name || this.type === tt._var) {
- var value = this.value;
- if (this.qml_eatPrimitiveType(value)) {
- node.isPrimitive = true;
- node.primitive = value;
- } else if (this.eatContextual(qtt._alias)) {
- return this.finishNode(node, qtt._alias);
- } else {
- node.isPrimitive = false;
- node.qualifiedId = this.qml_parseQualifiedId();
- }
- } else {
- this.unexpected();
- }
-
- return this.finishNode(node, "QMLType");
- }
-
- /*
- * Parses a Qualified ID of the form:
- * ('.' )*
- */
- pp.qml_parseQualifiedId = function() {
- var node = this.startNode();
-
- node.parts = [];
- if (!this.qml_isIdent(this.type, this.value)) {
- this.unexpected();
- }
- var id = this.value;
- this.next();
- node.parts.push(id);
- while(this.type === tt.dot) {
- id += '.';
- this.next();
- if (!this.qml_isIdent(this.type, this.value)) {
- this.unexpected();
- }
- id += this.value;
- node.parts.push(this.value);
- this.next();
- }
- node.raw = id;
-
- return this.finishNode(node, "QMLQualifiedID");
- }
-
- /*
- * Parses an Identifier in a QML Context. That is, this method uses 'isQMLContextual'
- * to throw an error if a non-contextual QML keyword is found.
- */
- pp.qml_parseIdent = function(liberal) {
- // Check for non-contextual QML keywords
- if (this.type === tt.name) {
- for (var key in keywords) {
- if (!keywords[key].isQMLContextual && this.isContextual(key)) {
- this.unexpected();
- }
- }
- }
- return this.parseIdent(liberal);
- }
-
- /*
- * Returns whether or not a given token type and name can be a QML Identifier.
- * Uses the 'isQMLContextual' boolean of 'keywords' to determine this.
- */
- pp.qml_isIdent = function(type, name) {
- if (type === tt.name) {
- var key;
- if (key = keywords[name]) {
- return key.isQMLContextual
- }
- return true;
- }
- return false;
- }
-
- /*
- * Returns whether or not the current token is a QML primitive type and consumes
- * it as a side effect if it is.
- */
- pp.qml_eatPrimitiveType = function(name) {
- if (this.qml_isPrimitiveType(name)) {
- this.next();
- return true;
- }
- return false;
- }
-
- /*
- * Returns whether or not the current token is a QML primitive type.
- */
- pp.qml_isPrimitiveType = function(name) {
- if (name === "var") {
- return true;
- }
-
- var key;
- if (key = keywords[name]) {
- return key.isPrimitive;
- }
- return false;
- }
-
- acorn.plugins.qml = function(instance) {
-
- // Extend acorn's 'parseTopLevel' method
- instance.extend("parseTopLevel", function(nextMethod) {
- return function(node) {
- // Most of QML's constructs sit at the top-level of the parse tree,
- // 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.
- if (!node.body) {
- node.body = [];
- }
-
- var headerStmts = this.qml_parseHeaderStatements();
- if (headerStmts !== undefined) {
- node.body.push(headerStmts);
- }
-
- if (this.type !== tt.eof) {
- var objRoot = this.qml_parseObjectLiteral();
- if (objRoot !== undefined) {
- node.body.push(objRoot);
- }
- }
-
- if (!this.eat(tt.eof)) {
- this.raise(this.pos, "Expected EOF after QML Root Object");
- }
-
- return this.finishNode(node, "Program");
- };
- });
- }
-
- return acorn;
-};
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/build.properties b/qt/org.eclipse.cdt.qt.core.acorn/build.properties
deleted file mode 100644
index 41eb6ade2b4..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/build.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/plugin.properties b/qt/org.eclipse.cdt.qt.core.acorn/plugin.properties
deleted file mode 100644
index 7ed20d4606f..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/plugin.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2013 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
-
-pluginName=C/C++ Qt Acorn QML Parser
-providerName=Eclipse CDT
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/pom.xml b/qt/org.eclipse.cdt.qt.core.acorn/pom.xml
deleted file mode 100644
index 8bdb21a8da6..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/pom.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
- 4.0.0
-
-
- org.eclipse.cdt
- cdt-parent
- 8.8.0-SNAPSHOT
- ../../pom.xml
-
-
- 2.0.0-SNAPSHOT
- org.eclipse.cdt.qt.core.acorn
- eclipse-plugin
-
-
-
-
- maven-antrun-plugin
-
-
- generate-parsers
- generate-sources
-
- run
-
-
-
-
-
-
-
-
- clean-parsers
- clean
-
- run
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/src/org/eclipse/cdt/qt/core/acorn/Activator.java b/qt/org.eclipse.cdt.qt.core.acorn/src/org/eclipse/cdt/qt/core/acorn/Activator.java
deleted file mode 100644
index e4f60a0bc89..00000000000
--- a/qt/org.eclipse.cdt.qt.core.acorn/src/org/eclipse/cdt/qt/core/acorn/Activator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * 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.acorn;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class Activator implements BundleActivator {
-
- private static BundleContext context;
-
- static BundleContext getContext() {
- return context;
- }
-
- /*
- * (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
- */
- public void start(BundleContext bundleContext) throws Exception {
- Activator.context = bundleContext;
- }
-
- /*
- * (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
- */
- public void stop(BundleContext bundleContext) throws Exception {
- Activator.context = null;
- }
-
-}
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/.gitignore b/qt/org.eclipse.cdt.qt.core/acorn-qml/.gitignore
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/.gitignore
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/.gitignore
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/bin/acorn-qml.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/bin/acorn-qml.js
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/bin/acorn-qml.js
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/bin/acorn-qml.js
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/index.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/index.js
similarity index 52%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/index.js
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/index.js
index 282e1f47250..32c4d1dfd90 100644
--- a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/index.js
+++ b/qt/org.eclipse.cdt.qt.core/acorn-qml/index.js
@@ -10,4 +10,15 @@
*******************************************************************************/
'use strict';
-module.exports = require('./inject')(require('acorn'));
\ No newline at end of file
+// This will only be visible globally if we are in a browser environment
+var acornQML;
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ return module.exports = mod(require("./inject.js"), require("acorn"));
+ if (typeof define == "function" && define.amd) // AMD
+ return define(["./inject.js", "acorn/dist/acorn"], mod);
+ acornQML = mod(injectQML, acorn); // Plain browser env
+})(function(injectQML, acorn) {
+ return injectQML(acorn);
+})
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core/acorn-qml/inject.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/inject.js
new file mode 100644
index 00000000000..c176fd9af7b
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/acorn-qml/inject.js
@@ -0,0 +1,529 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+'use strict';
+
+// This will only be visible globally if we are in a browser environment
+var injectQML;
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ return module.exports = mod();
+ if (typeof define == "function" && define.amd) // AMD
+ return define([], mod);
+ injectQML = mod(); // Plain browser env
+})(function() {
+ return function(acorn) {
+ // Acorn token types
+ var tt = acorn.tokTypes;
+
+ // QML token types
+ var qtt = {};
+ var keywords = {};
+
+ /*
+ * Shorthand for defining keywords in the 'keywords' variable with the following
+ * format:
+ * keywords[name].isPrimitive : if this is a primitive type
+ * keywords[name].isQMLContextual : if this is a contextual keyword for QML
+ *
+ * Also stores the token's name in qtt._ for easy referencing later. None
+ * of these keywords will be tokenized and, as such, are allowed to be used in
+ * JavaScript expressions by acorn. The 'isQMLContextual' boolean in keywords refers
+ * to those contextual keywords that are also contextual in QML's parser rules such
+ * as 'color', 'list', 'alias', etc.
+ */
+ function kw(name, options) {
+ if (options === undefined)
+ options = {};
+ qtt["_" + name] = name;
+ keywords[name] = {};
+ keywords[name].isPrimitive = options.isPrimitive ? true : false;
+ keywords[name].isQMLContextual = options.isQMLContextual ? true : false;
+ }
+
+ // QML keywords
+ kw("import");
+ kw("pragma");
+ kw("property", { isQMLContextual : true });
+ kw("readonly", { isQMLContextual : true });
+ kw("signal", { isQMLContextual : true });
+ kw("as");
+ kw("boolean", { isPrimitive: true });
+ kw("double", { isPrimitive: true });
+ kw("int", { isPrimitive: true });
+ kw("alias", { isQMLContextual: true });
+ kw("list", { isPrimitive: true, isQMLContextual: true });
+ kw("color", { isPrimitive: true, isQMLContextual: true });
+ kw("real", { isPrimitive: true, isQMLContextual: true });
+ kw("string", { isPrimitive: true, isQMLContextual: true });
+ kw("url", { isPrimitive: true, isQMLContextual: true });
+
+ // Future reserved words
+ kw("transient");
+ kw("synchronized");
+ kw("abstract");
+ kw("volatile");
+ kw("native");
+ kw("goto");
+ kw("byte");
+ kw("long");
+ kw("char");
+ kw("short");
+ kw("float");
+
+ // QML parser methods
+ var pp = acorn.Parser.prototype;
+
+ /*
+ * Parses a set of QML Header Statements which can either be of
+ * the type import or pragma
+ */
+ pp.qml_parseHeaderStatements = function() {
+ var node = this.startNode()
+ node.statements = [];
+
+ var loop = true;
+ while (loop) {
+ if (this.type === tt._import || this.isContextual(qtt._import)) {
+ var qmlImport = this.qml_parseImportStatement();
+ node.statements.push(qmlImport);
+ } else if (this.isContextual(qtt._pragma)) {
+ var qmlPragma = this.qml_parsePragmaStatement();
+ node.statements.push(qmlPragma);
+ } else {
+ loop = false;
+ }
+ }
+
+ if (node.statements.length > 0) {
+ return this.finishNode(node, "QMLHeaderStatements");
+ }
+ return undefined;
+ }
+
+ /*
+ * Parses a QML Pragma statement of the form:
+ * 'pragma'
+ */
+ pp.qml_parsePragmaStatement = function() {
+ var node = this.startNode();
+ this.next();
+ node.identifier = this.parseIdent(false);
+ this.semicolon();
+ return this.finishNode(node, "QMLPragmaStatement");
+ }
+
+ /*
+ * Parses a QML Import statement of the form:
+ * 'import' [as ]
+ * 'import' [as ]
+ *
+ * as specified by http://doc.qt.io/qt-5/qtqml-syntax-imports.html
+ */
+ pp.qml_parseImportStatement = function() {
+ var node = this.startNode();
+ this.next();
+
+ // The type of import varies solely on the next token
+ switch(this.type) {
+ case tt.name:
+ node.module = this.qml_parseModule();
+ break;
+ case tt.string:
+ node.directoryPath = this.parseLiteral(this.value);
+ break;
+ default:
+ this.unexpected();
+ break;
+ }
+
+ // Parse the qualifier, if any
+ if (this.isContextual(qtt._as)) {
+ node.qualifier = this.qml_parseQualifier();
+ }
+
+ this.semicolon();
+ return this.finishNode(node, "QMLImportStatement");
+ };
+
+ /*
+ * Parses a QML Module of the form:
+ *
+ */
+ pp.qml_parseModule = function() {
+ var node = this.startNode();
+
+ node.qualifiedId = this.qml_parseQualifiedId();
+ if (this.type === tt.num) {
+ node.version = this.qml_parseVersionLiteral();
+ } else {
+ this.unexpected();
+ }
+
+ return this.finishNode(node, "QMLModule");
+ };
+
+ /*
+ * Parses a QML Version Literal which consists of a major and minor
+ * version separated by a '.'
+ */
+ pp.qml_parseVersionLiteral = function() {
+ var node = this.startNode();
+
+ node.raw = this.input.slice(this.start, this.end);
+ node.value = this.value;
+ var matches;
+ if (matches = /(\d+)\.(\d+)/.exec(node.raw)) {
+ node.major = parseInt(matches[1]);
+ node.minor = parseInt(matches[2]);
+ } else {
+ this.raise(this.start, "QML module must specify major and minor version");
+ }
+
+ this.next();
+ return this.finishNode(node, "QMLVersionLiteral");
+ }
+
+ /*
+ * Parses a QML Qualifier of the form:
+ * 'as'
+ */
+ pp.qml_parseQualifier = function() {
+ var node = this.startNode();
+ this.next();
+ node.identifier = this.qml_parseIdent(false);
+ return this.finishNode(node, "QMLQualifier");
+ }
+
+ /*
+ * Parses a QML Object Literal of the form:
+ * { ()* }
+ *
+ * http://doc.qt.io/qt-5/qtqml-syntax-basics.html#object-declarations
+ */
+ pp.qml_parseObjectLiteral = function(node) {
+ if (!node) {
+ node = this.startNode();
+ }
+ if (!node.qualifiedId) {
+ node.qualifiedId = this.qml_parseQualifiedId();
+ }
+ node.block = this.qml_parseMemberBlock();
+ return this.finishNode(node, "QMLObjectLiteral");
+ }
+
+ /*
+ * Parses a QML Member Block of the form:
+ * { * }
+ */
+ pp.qml_parseMemberBlock = function() {
+ var node = this.startNode();
+ this.expect(tt.braceL);
+ node.members = [];
+ while (!this.eat(tt.braceR)) {
+ node.members.push(this.qml_parseMember());
+ }
+ return this.finishNode(node, "QMLMemberBlock");
+ }
+
+ /*
+ * Parses a QML Member which can be one of the following:
+ * - a QML Property Binding
+ * - a Property Declaration (or Alias)
+ * - a QML Object Literal
+ * - a JavaScript Function Declaration
+ * - a Signal Definition
+ */
+ pp.qml_parseMember = function() {
+ var node = this.startNode();
+
+ if (this.type === tt._default
+ || this.isContextual(qtt._default)
+ || this.isContextual(qtt._readonly)
+ || this.isContextual(qtt._property)) {
+ return this.qml_parsePropertyDeclaration(node);
+ } else if (this.isContextual(qtt._signal)) {
+ return this.qml_parseSignalDefinition(node);
+ } else if (this.type === tt._function) {
+ return this.parseFunctionStatement(node);
+ }
+
+ node.qualifiedId = this.qml_parseQualifiedId();
+ switch(this.type) {
+ case tt.braceL:
+ return this.qml_parseObjectLiteral(node);
+ case tt.colon:
+ return this.qml_parseProperty(node);
+ }
+
+ this.unexpected();
+ }
+
+ /*
+ * Parses a QML Property of the form:
+ *
+ */
+ pp.qml_parseProperty = function(node) {
+ if (!node) {
+ node = this.startNode();
+ }
+ if (!node.qualifiedId) {
+ node.qualifiedId = this.qml_parseQualifiedId();
+ }
+ node.binding = this.qml_parseBinding();
+ return this.finishNode(node, "QMLProperty");
+ }
+
+ /*
+ * Parses a QML Signal Definition of the form:
+ * 'signal' [( [',' ]* )]?
+ */
+ pp.qml_parseSignalDefinition = function(node) {
+ if (!node) {
+ node = this.startNode();
+ }
+ this.next();
+ node.identifier = this.qml_parseIdent(false);
+ node.parameters = [];
+ if (this.type === tt.parenL) {
+ this.next();
+ if (this.type !== tt.parenR) {
+ do {
+ var paramNode = this.startNode();
+ paramNode.type = this.qml_parseIdent(false);
+ paramNode.identifier = this.qml_parseIdent(false);
+ node.parameters.push(paramNode);
+ } while(this.eat(tt.comma));
+ }
+ if (!this.eat(tt.parenR)) {
+ this.unexpected();
+ }
+ }
+ this.semicolon();
+ return this.finishNode(node, "QMLSignalDefinition");
+ }
+
+ /*
+ * Parses a QML Property Declaration (or Alias) of the form:
+ * ['default'|'readonly'] 'property' []
+ */
+ pp.qml_parsePropertyDeclaration = function(node) {
+ node["default"] = false;
+ node["readonly"] = false;
+
+ if (this.type === tt._default || this.isContextual(qtt._default)) {
+ node["default"] = true;
+ this.next();
+ } else if (this.eatContextual(qtt._readonly)) {
+ node["readonly"] = true;
+ }
+ this.expectContextual(qtt._property);
+ node.typeInfo = this.qml_parseType();
+ node.identifier = this.qml_parseIdent(false);
+ if (this.type !== tt.colon) {
+ this.semicolon();
+ } else {
+ node.binding = this.qml_parseBinding();
+ }
+
+ if (node.typeInfo.type === qtt._alias) {
+ node.typeInfo = undefined;
+ return this.finishNode(node, "QMLPropertyAlias");
+ }
+ return this.finishNode(node, "QMLPropertyDeclaration");
+ }
+
+ /*
+ * Parses a QML Binding of the form:
+ * ':' (|)
+ */
+ pp.qml_parseBinding = function() {
+ var node = this.startNode();
+ this.expect(tt.colon);
+
+ // TODO: solve ambiguity where a QML Object Literal starts with a
+ // Qualified Id that looks very similar to a MemberExpression in
+ // JavaScript. For now, we just won't parse statements like:
+ // test: QMLObject { }
+ // test: QMLObject.QualifiedId { }
+
+ if (this.type === tt.braceL) {
+ node.block = this.qml_parseStatementBlock();
+ return this.finishNode(node, "QMLBinding");
+ }
+ node.expr = this.parseExpression(false);
+ this.semicolon();
+ return this.finishNode(node, "QMLBinding");
+ }
+
+ /*
+ * Parses a QML Statement Block of the form:
+ * { * }
+ */
+ pp.qml_parseStatementBlock = function() {
+ var node = this.startNode();
+ this.expect(tt.braceL);
+ node.statements = [];
+ while(!this.eat(tt.braceR)) {
+ node.statements.push(this.parseStatement(true, false));
+ }
+ return this.finishNode(node, "QMLStatementBlock");
+ }
+
+ /*
+ * Parses a QML Type which can be either a Qualified ID or a primitive type keyword.
+ * Returns a node of type qtt._alias if the type keyword parsed was "alias".
+ */
+ pp.qml_parseType = function() {
+ var node = this.startNode();
+
+ if (this.type === tt.name || this.type === tt._var) {
+ var value = this.value;
+ if (this.qml_eatPrimitiveType(value)) {
+ node.isPrimitive = true;
+ node.primitive = value;
+ } else if (this.eatContextual(qtt._alias)) {
+ return this.finishNode(node, qtt._alias);
+ } else {
+ node.isPrimitive = false;
+ node.qualifiedId = this.qml_parseQualifiedId();
+ }
+ } else {
+ this.unexpected();
+ }
+
+ return this.finishNode(node, "QMLType");
+ }
+
+ /*
+ * Parses a Qualified ID of the form:
+ * ('.' )*
+ */
+ pp.qml_parseQualifiedId = function() {
+ var node = this.startNode();
+
+ node.parts = [];
+ if (!this.qml_isIdent(this.type, this.value)) {
+ this.unexpected();
+ }
+ var id = this.value;
+ this.next();
+ node.parts.push(id);
+ while(this.type === tt.dot) {
+ id += '.';
+ this.next();
+ if (!this.qml_isIdent(this.type, this.value)) {
+ this.unexpected();
+ }
+ id += this.value;
+ node.parts.push(this.value);
+ this.next();
+ }
+ node.raw = id;
+
+ return this.finishNode(node, "QMLQualifiedID");
+ }
+
+ /*
+ * Parses an Identifier in a QML Context. That is, this method uses 'isQMLContextual'
+ * to throw an error if a non-contextual QML keyword is found.
+ */
+ pp.qml_parseIdent = function(liberal) {
+ // Check for non-contextual QML keywords
+ if (this.type === tt.name) {
+ for (var key in keywords) {
+ if (!keywords[key].isQMLContextual && this.isContextual(key)) {
+ this.unexpected();
+ }
+ }
+ }
+ return this.parseIdent(liberal);
+ }
+
+ /*
+ * Returns whether or not a given token type and name can be a QML Identifier.
+ * Uses the 'isQMLContextual' boolean of 'keywords' to determine this.
+ */
+ pp.qml_isIdent = function(type, name) {
+ if (type === tt.name) {
+ var key;
+ if (key = keywords[name]) {
+ return key.isQMLContextual
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Returns whether or not the current token is a QML primitive type and consumes
+ * it as a side effect if it is.
+ */
+ pp.qml_eatPrimitiveType = function(name) {
+ if (this.qml_isPrimitiveType(name)) {
+ this.next();
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Returns whether or not the current token is a QML primitive type.
+ */
+ pp.qml_isPrimitiveType = function(name) {
+ if (name === "var") {
+ return true;
+ }
+
+ var key;
+ if (key = keywords[name]) {
+ return key.isPrimitive;
+ }
+ return false;
+ }
+
+ acorn.plugins.qml = function(instance) {
+
+ // Extend acorn's 'parseTopLevel' method
+ instance.extend("parseTopLevel", function(nextMethod) {
+ return function(node) {
+ // Most of QML's constructs sit at the top-level of the parse tree,
+ // 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.
+ if (!node.body) {
+ node.body = [];
+ }
+
+ var headerStmts = this.qml_parseHeaderStatements();
+ if (headerStmts !== undefined) {
+ node.body.push(headerStmts);
+ }
+
+ if (this.type !== tt.eof) {
+ var objRoot = this.qml_parseObjectLiteral();
+ if (objRoot !== undefined) {
+ node.body.push(objRoot);
+ }
+ }
+
+ if (!this.eat(tt.eof)) {
+ this.raise(this.pos, "Expected EOF after QML Root Object");
+ }
+
+ return this.finishNode(node, "Program");
+ };
+ });
+ }
+
+ return acorn;
+ };
+})
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/package.json b/qt/org.eclipse.cdt.qt.core/acorn-qml/package.json
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/package.json
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/package.json
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/driver.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/test/driver.js
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/driver.js
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/test/driver.js
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/run.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/test/run.js
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/run.js
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/test/run.js
diff --git a/qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/tests-qml.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/test/tests-qml.js
similarity index 100%
rename from qt/org.eclipse.cdt.qt.core.acorn/acorn-qml/test/tests-qml.js
rename to qt/org.eclipse.cdt.qt.core/acorn-qml/test/tests-qml.js
diff --git a/qt/org.eclipse.cdt.qt.core/acorn-qml/walk/walk.js b/qt/org.eclipse.cdt.qt.core/acorn-qml/walk/walk.js
new file mode 100644
index 00000000000..a753f3e3f07
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/acorn-qml/walk/walk.js
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+'use strict';
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ return mod(require("acorn/walk"));
+ if (typeof define == "function" && define.amd) // AMD
+ return define([ "acorn/dist/walk" ], mod);
+ mod(acorn.walk); // Plain browser env
+})(function(walk) {
+ function skipThrough(node, st, c) { c(node, st) }
+ function ignore(node, st, c) {}
+
+ var base = walk.base;
+ base["Program"] = function(node, st, c) {
+ for (var i = 0; i < node.body.length; i++) {
+ var nodeBody = node.body[i];
+ if (node.body[i].type === "QMLObjectLiteral") {
+ c(node.body[i], st, "QMLRootObject");
+ } else {
+ c(node.body[i], st);
+ }
+ }
+ }
+ base["QMLHeaderStatements"] = function(node, st, c) {
+ for (var i = 0; i < node.statements.length; i++) {
+ c(node.statements[i], st, "QMLHeaderStatement");
+ }
+ }
+ base["QMLHeaderStatement"] = skipThrough;
+ base["QMLImportStatement"] = function(node, st, c) {
+ c(node.module, st);
+ }
+ base["QMLModule"] = ignore;
+ base["QMLPragmaStatement"] = ignore;
+ base["QMLRootObject"] = skipThrough;
+ base["QMLObjectLiteral"] = function(node, st, c) {
+ c(node.block, st);
+ }
+ base["QMLMemberBlock"] = function(node, st, c) {
+ for (var i = 0; i < node.members.length; i++) {
+ c(node.members[i], st, "QMLMember");
+ }
+ }
+ base["QMLMember"] = skipThrough;
+ base["QMLPropertyDeclaration"] = function(node, st, c) {
+ c(node.identifier, st, "Pattern");
+ c(node.binding, st);
+ }
+ base["QMLSignalDefinition"] = ignore;
+ base["QMLProperty"] = function(node, st, c) {
+ // c(node.qualifiedId, st)
+ c(node.binding, st);
+ }
+ base["QMLBinding"] = function(node, st, c) {
+ if (node.block) {
+ c(node.block, st);
+ } else {
+ c(node.expr, st, "Expression");
+ }
+ }
+ base["QMLStatementBlock"] = function(node, st, c) {
+ for (var i = 0; i < node.statements.length; i++) {
+ c(node.statements[i], st, "Statement");
+ }
+ }
+})
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core/tern-qml/.gitignore b/qt/org.eclipse.cdt.qt.core/tern-qml/.gitignore
new file mode 100644
index 00000000000..4e050c365a2
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/tern-qml/.gitignore
@@ -0,0 +1,4 @@
+/node_modules
+/.settings
+.project
+.tern-project
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core/tern-qml/.npmignore b/qt/org.eclipse.cdt.qt.core/tern-qml/.npmignore
new file mode 100644
index 00000000000..ebc5ac557a4
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/tern-qml/.npmignore
@@ -0,0 +1,5 @@
+/test
+/node_modules
+/.settings
+.project
+.tern-project
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core/tern-qml/demo/qml-demo.html b/qt/org.eclipse.cdt.qt.core/tern-qml/demo/qml-demo.html
new file mode 100644
index 00000000000..210a407a201
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/tern-qml/demo/qml-demo.html
@@ -0,0 +1,97 @@
+
+
+
+
+ QML Tern Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Demo with QML Tern plugin
+
+
+
+
diff --git a/qt/org.eclipse.cdt.qt.core/tern-qml/package.json b/qt/org.eclipse.cdt.qt.core/tern-qml/package.json
new file mode 100644
index 00000000000..2074871072f
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/tern-qml/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "tern-qt",
+ "description": "Tern Qt Plugin",
+ "version": "0.0.0",
+ "dependencies": {
+ "tern": "^0.16.0",
+ "acorn": "^2.4.0",
+ "acorn-qml": "../acorn-qml"
+ },
+ "devDependencies": {
+ "test": ">=0.0.5",
+ "codemirror": "^5.6.0",
+ "codemirror-extension": "^0.1.0",
+ "codemirror-javascript": "^0.1.0"
+ }
+}
\ No newline at end of file
diff --git a/qt/org.eclipse.cdt.qt.core/tern-qml/qml.js b/qt/org.eclipse.cdt.qt.core/tern-qml/qml.js
new file mode 100644
index 00000000000..1e7ac7752f6
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/tern-qml/qml.js
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+"use strict";
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ return mod(require("tern/lib/infer"), require("tern/lib/tern"));
+ if (typeof define == "function" && define.amd) // AMD
+ return define([ "tern/lib/infer", "tern/lib/tern" ], mod);
+ mod(tern, tern); // Plain browser env
+})(function(infer, tern) {
+ // Define a few shorthand variables/functions
+ var Scope = infer.Scope;
+ function skipThrough(node, st, c) { c(node, st) }
+ function ignore(node, st, c) {}
+
+ // Register the QML plugin in Tern
+ tern.registerPlugin("qml", function(server) {
+ extendTernScopeGatherer(infer.scopeGatherer);
+ extendTernInferWrapper(infer.inferWrapper);
+ extendTernTypeFinder(infer.typeFinder);
+ extendTernSearchVisitor(infer.searchVisitor);
+ server.on("preParse", preParse);
+ });
+
+ function preParse(text, options) {
+ var plugins = options.plugins;
+ if (!plugins) plugins = options.plugins = {};
+ plugins["qml"] = true;
+ }
+
+ function extendTernScopeGatherer(scopeGatherer) {
+ scopeGatherer["QMLModule"] = function(node, scope, c) {
+ scope.defProp(node.qualifiedId.raw, node.qualifiedId);
+ }
+ scopeGatherer["QMLMemberBlock"] = function(node, scope, c) {
+ var inner = node.scope = new Scope(scope, node);
+ for (var i = 0; i < node.members.length; i++) {
+ c(node.members[i], inner, "QMLMember");
+ }
+ }
+ scopeGatherer["QMLStatementBlock"] = function(node, scope, c) {
+ var inner = node.scope = new Scope(scope, node);
+ for (var i = 0; i < node.statements.length; i++) {
+ c(node.statements[i], inner, "Statement");
+ }
+ }
+ }
+
+ function extendTernInferWrapper(inferWrapper) {
+ // TODO: Implement the AST walk methods for inferWrapper
+ }
+
+ function extendTernTypeFinder(typeFinder) {
+ // TODO: Implement the AST walk methods for typeFinder
+ }
+
+ function extendTernSearchVisitor(searchVisitor) {
+ // TODO: Implement the AST walk methods for searchVisitor
+ }
+})
\ No newline at end of file