diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.java b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.java
new file mode 100644
index 0000000000..c858e94f64
--- /dev/null
+++ b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2016 NumberFour AG.
+ * 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:
+ * NumberFour AG - Initial API and implementation
+ */
+package org.eclipse.n4js.scoping.utils;
+
+import static org.eclipse.xtext.xbase.lib.IterableExtensions.last;
+
+import java.util.Arrays;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.n4js.n4JS.AssignmentExpression;
+import org.eclipse.n4js.n4JS.AssignmentOperator;
+import org.eclipse.n4js.n4JS.BinaryLogicalExpression;
+import org.eclipse.n4js.n4JS.CommaExpression;
+import org.eclipse.n4js.n4JS.Expression;
+import org.eclipse.n4js.n4JS.ParenExpression;
+import org.eclipse.n4js.n4JS.PostfixExpression;
+import org.eclipse.n4js.n4JS.UnaryExpression;
+import org.eclipse.n4js.n4JS.UnaryOperator;
+import org.eclipse.xtext.EcoreUtil2;
+
+/**
+ * General utility methods for expressions.
+ */
+public class ExpressionExtensions {
+
+ /**
+ * Returns true if the subExpression actually is the left hand side expression of an assignment expression, that is
+ * its value could be changed when the assignment is evaluated. I.e. the subExpression could be returned by ancestor
+ * expression, e.g., if the subExpression is an operand of a binary logical expression. This method returns false,
+ * if the subExpression is an assignment expression itself!
+ *
+ * Note that neither assignments nor conditional expression return any of their operands!
+ */
+ public static boolean isLeftHandSide(EObject subExpression) {
+ if (subExpression == null || subExpression instanceof AssignmentExpression) {
+ return false;
+ }
+ EObject expr = subExpression;
+ while (expr.eContainer() != null && isPotentialEvalResult(expr.eContainer(), expr)) {
+ expr = expr.eContainer();
+ }
+ return expr.eContainer() instanceof AssignmentExpression &&
+ ((AssignmentExpression) expr.eContainer()).getLhs() == expr;
+ }
+
+ /**
+ * Does the argument occur as operand in a (prefix or postfix) ++ or -- operation?
+ *
+ * The increment and decrement operators "conceptually" involve both read- and write-access, unlike the LHS of a
+ * simple assignment. Granted, '+=' and similar compound assignments can be seen as comprising read- and
+ * write-access.
+ */
+ public static boolean isIncOrDecTarget(EObject subExpression) {
+ if (subExpression == null || subExpression instanceof AssignmentExpression) {
+ return false;
+ }
+ EObject expr = subExpression;
+ while (expr.eContainer() != null && isPotentialEvalResult(expr.eContainer(), expr)) {
+ expr = expr.eContainer();
+ }
+ if (expr.eContainer() instanceof PostfixExpression) {
+ return true;
+ }
+ if (expr.eContainer() instanceof UnaryExpression) {
+ UnaryExpression ue = (UnaryExpression) expr.eContainer();
+ if (ue.getOp() == UnaryOperator.INC || ue.getOp() == UnaryOperator.DEC) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /***/
+ public static boolean isBothReadFromAndWrittenTo(EObject expr) {
+ if (isLeftHandSide(expr)) {
+ AssignmentExpression a = EcoreUtil2.getContainerOfType(expr, AssignmentExpression.class);
+ return a.getOp() != AssignmentOperator.ASSIGN;
+ }
+ return isIncOrDecTarget(expr);
+ }
+
+ /**
+ * Returns true if the (value of the) subExpression could be returned by container expression, e.g., if the
+ * subExpression is an operand of a binary logical expression.
+ *
+ * Most types of expressions return false here. Note that neither assignments nor conditional expression return any
+ * of their operands, thus, both type of expressions always return false as well.
+ *
+ * Example: the unparenthesized {@code arr[0]} below {@link #isLeftHandSide} although its direct container isn't an
+ * assignment but a {@link ParenExpression}
+ *
+ *
+ * {@code
+ * var arr = [1];
+ * (arr[0]) = 6;
+ * console.log(arr[0])
+ * }
+ *
+ */
+ private static boolean isPotentialEvalResult(final EObject container, final EObject childExpression) {
+ if (container instanceof ParenExpression && childExpression instanceof Expression) {
+ return isPotentialEvalResult((ParenExpression) container, (Expression) childExpression);
+ } else if (container instanceof BinaryLogicalExpression && childExpression instanceof Expression) {
+ return isPotentialEvalResult((BinaryLogicalExpression) container, (Expression) childExpression);
+ } else if (container instanceof CommaExpression && childExpression instanceof Expression) {
+ return isPotentialEvalResult((CommaExpression) container, (Expression) childExpression);
+ } else if (container != null && childExpression != null) {
+ return false;
+ } else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.asList(container, childExpression).toString());
+ }
+ }
+
+ private static boolean isPotentialEvalResult(ParenExpression container, Expression childExpression) {
+ return childExpression != null && childExpression.eContainer() == container;
+ }
+
+ private static boolean isPotentialEvalResult(BinaryLogicalExpression container, Expression childExpression) {
+ return childExpression != null && childExpression.eContainer() == container;
+ }
+
+ private static boolean isPotentialEvalResult(CommaExpression container, Expression childExpression) {
+ return container != null && last(container.getExprs()) == childExpression;
+ }
+
+}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.xtend b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.xtend
deleted file mode 100644
index 15b5bb7917..0000000000
--- a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ExpressionExtensions.xtend
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Copyright (c) 2016 NumberFour AG.
- * 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:
- * NumberFour AG - Initial API and implementation
- */
-package org.eclipse.n4js.scoping.utils
-
-import org.eclipse.n4js.n4JS.AssignmentExpression
-import org.eclipse.n4js.n4JS.BinaryLogicalExpression
-import org.eclipse.n4js.n4JS.CommaExpression
-import org.eclipse.n4js.n4JS.Expression
-import org.eclipse.emf.ecore.EObject
-import org.eclipse.n4js.n4JS.ParenExpression
-import org.eclipse.n4js.n4JS.PostfixExpression
-import org.eclipse.n4js.n4JS.UnaryExpression
-import org.eclipse.n4js.n4JS.UnaryOperator
-import org.eclipse.n4js.n4JS.AssignmentOperator
-import org.eclipse.xtext.EcoreUtil2
-
-/**
- * General utitility methods for expressions.
- */
-class ExpressionExtensions {
-
- /**
- * Returns true if the subExpression actually is the left hand side expression of an assignment expression, that is
- * its value could be changed when the assignment is evaluated. I.e. the subExpression
- * could be returned by ancestor expression, e.g., if the subExpression is
- * an operand of a binary logical expression.
- * This method returns false, if the subExpression is an assignment expression itself!
- *
- * Note that neither assignments nor conditional expression return any of their operands!
- */
- static def boolean isLeftHandSide(EObject subExpression) {
- if (subExpression === null || subExpression instanceof AssignmentExpression) {
- return false;
- }
- var EObject expr = subExpression;
- while (expr.eContainer!==null && isPotentialEvalResult(expr.eContainer, expr)) {
- expr = expr.eContainer;
- }
- return expr !== null && expr.eContainer instanceof AssignmentExpression &&
- (expr.eContainer as AssignmentExpression).lhs == expr
- }
-
-
- /**
- * Does the argument occur as operand in a (prefix or postfix) ++ or -- operation?
- *
- * The increment and decrement operators "conceptually" involve both read- and write-access,
- * unlike the LHS of a simple assignment. Granted, '+=' and similar compound assignments can be seen
- * as comprising read- and write-access.
- */
- static def boolean isIncOrDecTarget(EObject subExpression) {
- if (subExpression === null || subExpression instanceof AssignmentExpression) {
- return false;
- }
- var EObject expr = subExpression;
- while (expr.eContainer!==null && isPotentialEvalResult(expr.eContainer, expr)) {
- expr = expr.eContainer;
- }
- if (expr.eContainer instanceof PostfixExpression) {
- return true
- }
- if (expr.eContainer instanceof UnaryExpression) {
- val ue = expr.eContainer as UnaryExpression;
- if (ue.op == UnaryOperator.INC || ue.op === UnaryOperator.DEC) {
- return true
- }
- }
- return false
- }
-
- static def boolean isBothReadFromAndWrittenTo(EObject expr) {
- if (isLeftHandSide(expr)) {
- val a = EcoreUtil2.getContainerOfType(expr, AssignmentExpression)
- return a.op !== AssignmentOperator.ASSIGN
- }
- return isIncOrDecTarget(expr)
- }
-
- /**
- * Returns true if the (value of the) subExpression could be returned by container expression, e.g., if the subExpression is
- * an operand of a binary logical expression.
- *
- * Most types of expressions return false here. Note that neither assignments nor conditional expression return any of their operands, thus, both type of expressions
- * always return false as well.
- *
- * Example: the unparenthesized {@code arr[0]} below {@link #isLeftHandSide} although its direct container isn't an assignment but a {@link ParenExpression}
- *
- * {@code
- * var arr = [1];
- * (arr[0]) = 6;
- * console.log(arr[0])
- * }
- *
- */
- private static def dispatch boolean isPotentialEvalResult(EObject container, EObject childExpression) {
- return false;
- }
-
- private static def dispatch boolean isPotentialEvalResult(ParenExpression container, Expression childExpression) {
- return childExpression !== null && childExpression.eContainer === container;
- }
-
- private static def dispatch boolean isPotentialEvalResult(BinaryLogicalExpression container, Expression childExpression) {
- return childExpression !== null && childExpression.eContainer === container;
- }
-
- private static def dispatch boolean isPotentialEvalResult(CommaExpression container, Expression childExpression) {
- return container !== null && container.exprs.last === childExpression;
- }
-}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.java b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.java
new file mode 100644
index 0000000000..50447bcca7
--- /dev/null
+++ b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright (c) 2016 NumberFour AG.
+ * 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:
+ * NumberFour AG - Initial API and implementation
+ */
+package org.eclipse.n4js.scoping.utils;
+
+import static org.eclipse.xtext.xbase.lib.IterableExtensions.filter;
+import static org.eclipse.xtext.xbase.lib.IterableExtensions.map;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.n4js.n4JS.N4NamespaceDeclaration;
+import org.eclipse.n4js.n4JS.Script;
+import org.eclipse.n4js.resource.N4JSCache;
+import org.eclipse.n4js.scoping.N4JSScopeProvider;
+import org.eclipse.n4js.scoping.imports.ImportedElementsScopingHelper;
+import org.eclipse.n4js.ts.typeRefs.FunctionTypeExpression;
+import org.eclipse.n4js.ts.types.AbstractNamespace;
+import org.eclipse.n4js.ts.types.TClassifier;
+import org.eclipse.n4js.ts.types.TEnum;
+import org.eclipse.n4js.ts.types.TModule;
+import org.eclipse.n4js.ts.types.TStructMember;
+import org.eclipse.n4js.ts.types.TStructMethod;
+import org.eclipse.n4js.ts.types.Type;
+import org.eclipse.xtext.resource.EObjectDescription;
+import org.eclipse.xtext.resource.IEObjectDescription;
+import org.eclipse.xtext.scoping.IScope;
+import org.eclipse.xtext.scoping.impl.SingletonScope;
+
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+/**
+ * Helper for {@link N4JSScopeProvider N4JSScopeProvider} using {@link ImportedElementsScopingHelper
+ * ImportedElementsScopingHelper} for providing scope for types provider.
+ */
+public class LocallyKnownTypesScopingHelper {
+
+ @Inject
+ N4JSCache cache;
+
+ @Inject
+ ImportedElementsScopingHelper importedElementsScopingHelper;
+
+ @Inject
+ ScopeSnapshotHelper scopeSnapshotHelper;
+
+ /** Returns the type itself and type variables in case the type is generic. */
+ public IScope scopeWithTypeAndItsTypeVariables(IScope parent, Type type, boolean staticAccess) {
+ IScope result = parent;
+ if (type != null) {
+
+ // add the type itself
+ if (type.getName() != null && type instanceof TClassifier) {
+ // note that functions cannot be used as type references
+ result = new SingletonScope(EObjectDescription.create(type.getName(), type), result);
+ }
+
+ // add the type variables
+ if (type.isGeneric()) {
+ if (type instanceof TClassifier && staticAccess) {
+ // error case: type variables of a classifier cannot be accessed from static members
+ // e.g. class C { static x: T; }
+ // --> return same scope as in success case, but wrap descriptions with a
+ // WrongStaticAccessorDescription
+ Function wrapEODs = dscr -> new WrongStaticAccessDescription(
+ dscr, staticAccess);
+ result = scopeSnapshotHelper.scopeForEObjects("scopeWithTypeAndItsTypeVariables-1",
+ type, result, type.getTypeVars(), wrapEODs);
+ } else {
+ // success case: simply add type variables to scope
+ result = scopeSnapshotHelper.scopeForEObjects("scopeWithTypeAndItsTypeVariables-2", type, result,
+ type.getTypeVars());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /** Returns the type variables if the TStructMethod is generic. */
+ public IScope scopeWithTypeVarsOfTStructMethod(IScope parent, TStructMethod m) {
+ TStructMember mDef = m.getDefinedMember();
+ if (mDef instanceof TStructMethod) {
+ if (((TStructMethod) mDef).isGeneric()) {
+ return scopeSnapshotHelper.scopeForEObjects("scopeWithTypeVarsOfTStructMethod", mDef, parent,
+ ((TStructMethod) mDef).getTypeVars());
+ }
+ }
+ return parent;
+ }
+
+ /** Returns the type variables if the function type expression is generic. */
+ public IScope scopeWithTypeVarsOfFunctionTypeExpression(IScope parent, FunctionTypeExpression funTypeExpr) {
+ if (funTypeExpr != null && funTypeExpr.isGeneric()) {
+ return scopeSnapshotHelper.scopeForEObjects("scopeWithTypeVarsOfFunctionTypeExpression", funTypeExpr,
+ parent, funTypeExpr.getTypeVars());
+ }
+ return parent;
+ }
+
+ /** Returns scope with locally known types and (as parent) import scope; the result is cached. */
+ public IScope scopeWithLocallyDeclaredElems(Script script, Supplier parentSupplier,
+ boolean onlyNamespacelikes) {
+ return cache.get(script.eResource(), () -> {
+ // all types in the index:
+ IScope parent = parentSupplier.get();
+ // but imported types are preferred (or maybe renamed with aliases):
+ IScope importScope = importedElementsScopingHelper.getImportedTypes(parent, script);
+ // finally, add locally declared types as the outer scope
+ IScope localTypes = scopeWithLocallyDeclaredElems(script, importScope, onlyNamespacelikes);
+
+ return localTypes;
+ }, script, "locallyKnownTypes_" + String.valueOf(onlyNamespacelikes));
+ }
+
+ /** Returns scope with locally declared types (without import scope). */
+ public IScope scopeWithLocallyDeclaredElems(Script script, IScope parent, boolean onlyNamespacelikes) {
+ return scopeWithLocallyDeclaredElems(script.getModule(), script, parent, onlyNamespacelikes);
+ }
+
+ /** Returns scope with locally declared types (without import scope). */
+ public IScope scopeWithLocallyDeclaredElems(N4NamespaceDeclaration namespace, IScope parent,
+ boolean onlyNamespacelikes) {
+ return cache.get(namespace.eResource(),
+ () -> scopeWithLocallyDeclaredElems((AbstractNamespace) namespace.getDefinedType(), namespace, parent,
+ onlyNamespacelikes),
+ namespace, "scopeWithLocallyDeclaredElems_" + String.valueOf(onlyNamespacelikes));
+ }
+
+ /** Returns scope with locally declared types (without import scope). */
+ public IScope scopeWithLocallyDeclaredElems(AbstractNamespace namespace, IScope parent,
+ boolean onlyNamespacelikes) {
+ return scopeWithLocallyDeclaredElems(namespace, namespace, parent, onlyNamespacelikes);
+ }
+
+ /** Returns scope with locally declared types (without import scope). */
+ private IScope scopeWithLocallyDeclaredElems(AbstractNamespace ans, EObject context, IScope parent,
+ boolean onlyNamespacelikes) {
+ if (ans == null || ans.eIsProxy()) {
+ return parent;
+ }
+ Iterable tlElems = onlyNamespacelikes
+ ? Iterables.concat(ans.getNamespaces(), filter(ans.getTypes(), TEnum.class))
+ : filter(ans.getTypes(), t -> !t.isPolyfill());
+ Iterable eoDescrs = map(tlElems,
+ topLevelType -> EObjectDescription.create(topLevelType.getName(), topLevelType));
+ return scopeSnapshotHelper.scopeFor("scopeWithLocallyDeclaredTypes", context, parent, eoDescrs);
+ }
+
+ /**
+ * Returns scope with locally known types specially configured for super reference in case of polyfill definitions.
+ * It does not add the polyfillType itself. Instead, only its type variables are added, which are otherwise hidden
+ * in case of polyfills. The result is not cached as this scope is needed only one time.
+ */
+ public IScope scopeWithLocallyKnownTypesForPolyfillSuperRef(Script script, IScope parent, Type polyfillType) {
+
+ // imported and locally defined types are preferred (or maybe renamed with aliases):
+ IScope importScope = importedElementsScopingHelper.getImportedTypes(parent, script);
+
+ // locally defined types except polyfillType itself
+ TModule local = script.getModule();
+ Iterable eoDescrs = map(filter(local.getTypes(), t -> t != polyfillType),
+ t -> EObjectDescription.create(t.getName(), t));
+ IScope localTypesScope = scopeSnapshotHelper.scopeFor("scopeWithLocallyKnownTypesForPolyfillSuperRef", script,
+ importScope, eoDescrs);
+
+ // type variables of polyfill
+ if (polyfillType != null && polyfillType.isGeneric()) {
+ return scopeSnapshotHelper.scopeForEObjects("scopeWithLocallyKnownTypesForPolyfillSuperRef-polyfillType",
+ polyfillType, localTypesScope, polyfillType.getTypeVars());
+ }
+
+ // non generic:
+ return localTypesScope;
+
+ }
+
+}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.xtend b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.xtend
deleted file mode 100644
index df9692346a..0000000000
--- a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/LocallyKnownTypesScopingHelper.xtend
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Copyright (c) 2016 NumberFour AG.
- * 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:
- * NumberFour AG - Initial API and implementation
- */
-package org.eclipse.n4js.scoping.utils
-
-import com.google.common.collect.Iterables
-import com.google.inject.Inject
-import java.util.function.Supplier
-import org.eclipse.emf.ecore.EObject
-import org.eclipse.n4js.n4JS.N4NamespaceDeclaration
-import org.eclipse.n4js.n4JS.Script
-import org.eclipse.n4js.resource.N4JSCache
-import org.eclipse.n4js.scoping.N4JSScopeProvider
-import org.eclipse.n4js.scoping.imports.ImportedElementsScopingHelper
-import org.eclipse.n4js.ts.typeRefs.FunctionTypeExpression
-import org.eclipse.n4js.ts.types.AbstractNamespace
-import org.eclipse.n4js.ts.types.TClassifier
-import org.eclipse.n4js.ts.types.TEnum
-import org.eclipse.n4js.ts.types.TStructMethod
-import org.eclipse.n4js.ts.types.Type
-import org.eclipse.xtext.resource.EObjectDescription
-import org.eclipse.xtext.scoping.IScope
-import org.eclipse.xtext.scoping.impl.SingletonScope
-
-/**
- * Helper for {@link N4JSScopeProvider N4JSScopeProvider} using
- * {@link ImportedElementsScopingHelper ImportedElementsScopingHelper}
- * for providing scope for types provider.
- */
-class LocallyKnownTypesScopingHelper {
-
- @Inject
- N4JSCache cache
-
- @Inject
- ImportedElementsScopingHelper importedElementsScopingHelper
-
- @Inject
- ScopeSnapshotHelper scopeSnapshotHelper
-
- /** Returns the type itself and type variables in case the type is generic. */
- def IScope scopeWithTypeAndItsTypeVariables(IScope parent, Type type, boolean staticAccess) {
- var IScope result = parent;
- if (type !== null) {
-
- // add the type itself
- if (type.name !== null && type instanceof TClassifier) {
- // note that functions cannot be used as type references
- result = new SingletonScope(EObjectDescription.create(type.name, type), result)
- }
-
- // add the type variables
- if (type.generic) {
- if (type instanceof TClassifier && staticAccess) {
- // error case: type variables of a classifier cannot be accessed from static members
- // e.g. class C { static x: T; }
- // --> return same scope as in success case, but wrap descriptions with a WrongStaticAccessorDescription
- val wrapEODs = [new WrongStaticAccessDescription(it, staticAccess)];
- result = scopeSnapshotHelper.scopeForEObjects("scopeWithTypeAndItsTypeVariables-1", type, result, type.typeVars, wrapEODs);
- } else {
- // success case: simply add type variables to scope
- result = scopeSnapshotHelper.scopeForEObjects("scopeWithTypeAndItsTypeVariables-2", type, result, type.typeVars);
- }
- }
- }
-
- return result;
- }
-
- /** Returns the type variables if the TStructMethod is generic. */
- def IScope scopeWithTypeVarsOfTStructMethod(IScope parent, TStructMethod m) {
- val mDef = m.definedMember
- if (mDef instanceof TStructMethod) {
- if (mDef.generic) {
- return scopeSnapshotHelper.scopeForEObjects("scopeWithTypeVarsOfTStructMethod", mDef, parent, mDef.typeVars);
- }
- }
- return parent;
- }
-
- /** Returns the type variables if the function type expression is generic. */
- def IScope scopeWithTypeVarsOfFunctionTypeExpression(IScope parent, FunctionTypeExpression funTypeExpr) {
- if (funTypeExpr !== null && funTypeExpr.generic) {
- return scopeSnapshotHelper.scopeForEObjects("scopeWithTypeVarsOfFunctionTypeExpression", funTypeExpr, parent, funTypeExpr.typeVars);
- }
- return parent;
- }
-
- /** Returns scope with locally known types and (as parent) import scope; the result is cached. */
- def IScope scopeWithLocallyDeclaredElems(Script script, Supplier parentSupplier, boolean onlyNamespacelikes) {
- return cache.get(script.eResource, [|
- // all types in the index:
- val parent = parentSupplier.get();
- // but imported types are preferred (or maybe renamed with aliases):
- val IScope importScope = importedElementsScopingHelper.getImportedTypes(parent, script);
- // finally, add locally declared types as the outer scope
- val localTypes = scopeWithLocallyDeclaredElems(script, importScope, onlyNamespacelikes);
-
- return localTypes;
- ], script, 'locallyKnownTypes_'+String.valueOf(onlyNamespacelikes));
- }
-
- /** Returns scope with locally declared types (without import scope). */
- def IScope scopeWithLocallyDeclaredElems(Script script, IScope parent, boolean onlyNamespacelikes) {
- return scopeWithLocallyDeclaredElems(script.module, script, parent, onlyNamespacelikes);
- }
-
- /** Returns scope with locally declared types (without import scope). */
- def IScope scopeWithLocallyDeclaredElems(N4NamespaceDeclaration namespace, IScope parent, boolean onlyNamespacelikes) {
- return cache.get(namespace.eResource, [|
- return scopeWithLocallyDeclaredElems(namespace.definedType as AbstractNamespace, namespace, parent, onlyNamespacelikes);
- ], namespace, 'scopeWithLocallyDeclaredElems_'+String.valueOf(onlyNamespacelikes));
- }
-
- /** Returns scope with locally declared types (without import scope). */
- def IScope scopeWithLocallyDeclaredElems(AbstractNamespace namespace, IScope parent, boolean onlyNamespacelikes) {
- return scopeWithLocallyDeclaredElems(namespace, namespace, parent, onlyNamespacelikes);
- }
-
- /** Returns scope with locally declared types (without import scope). */
- def private IScope scopeWithLocallyDeclaredElems(AbstractNamespace ans, EObject context, IScope parent, boolean onlyNamespacelikes) {
- if (ans === null || ans.eIsProxy) {
- return parent;
- }
- val tlElems = if (onlyNamespacelikes) {
- Iterables.concat(ans.namespaces, ans.types.filter[t | t instanceof TEnum ])
- } else {
- ans.types.filter[t | !t.polyfill ];
- };
- val eoDescrs = tlElems.map[ topLevelType |
- return EObjectDescription.create(topLevelType.name, topLevelType);
- ];
- return scopeSnapshotHelper.scopeFor("scopeWithLocallyDeclaredTypes", context, parent, eoDescrs);
- }
-
- /**
- * Returns scope with locally known types specially configured for super reference in case of polyfill definitions.
- * It is comparable to {@link #getLocallyKnownTypes(Script, EReference, IScopeProvider), but it does not
- * add the polyfillType itself. Instead, only its type variables are added, which are otherwise hidden in case of polyfills.
- * The result is not cached as this scope is needed only one time.
- */
- def IScope scopeWithLocallyKnownTypesForPolyfillSuperRef(Script script,
- IScope parent, Type polyfillType) {
-
- // imported and locally defined types are preferred (or maybe renamed with aliases):
- val IScope importScope = importedElementsScopingHelper.getImportedTypes(parent, script)
-
- // locally defined types except polyfillType itself
- val local = script.module
- val eoDescrs = local.types.filter[it !== polyfillType].map[EObjectDescription.create(name, it)];
- val IScope localTypesScope = scopeSnapshotHelper.scopeFor("scopeWithLocallyKnownTypesForPolyfillSuperRef", script, importScope, eoDescrs);
-
- // type variables of polyfill
- if (polyfillType !== null && polyfillType.generic) {
- return scopeSnapshotHelper.scopeForEObjects("scopeWithLocallyKnownTypesForPolyfillSuperRef-polyfillType", polyfillType, localTypesScope, polyfillType.typeVars);
- }
-
- // non generic:
- return localTypesScope;
-
- }
-
-}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.java b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.java
new file mode 100644
index 0000000000..16cc6b8992
--- /dev/null
+++ b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2016 NumberFour AG.
+ * 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:
+ * NumberFour AG - Initial API and implementation
+ */
+package org.eclipse.n4js.scoping.utils;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.n4js.validation.JavaScriptVariantHelper;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.IEObjectDescription;
+import org.eclipse.xtext.scoping.IScope;
+import org.eclipse.xtext.scoping.Scopes;
+import org.eclipse.xtext.scoping.impl.MapBasedScope;
+import org.eclipse.xtext.scoping.impl.MultimapBasedScope;
+import org.eclipse.xtext.scoping.impl.SimpleScope;
+import org.eclipse.xtext.util.SimpleAttributeResolver;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+/**
+ * Some utility methods, similar to xtext's {@link Scopes}.
+ */
+public class ScopesHelper {
+
+ @Inject
+ private JavaScriptVariantHelper javaScriptVariantHelper;
+
+ /**
+ * Creates a map based scope for the given iterable of descriptions.
+ *
+ * @param context
+ * The context of the scope
+ * @param descriptions
+ * The descriptions
+ */
+ public IScope mapBasedScopeFor(EObject context, Iterable descriptions) {
+ return mapBasedScopeFor(context, IScope.NULLSCOPE, descriptions);
+ }
+
+ /**
+ * Creates a map based scope for the given iterable of descriptions.
+ *
+ * @param context
+ * The context of the scope
+ * @param parent
+ * The parent scope
+ * @param descriptions
+ * The descriptions
+ */
+ public IScope mapBasedScopeFor(EObject context, IScope parent, Iterable descriptions) {
+ if (javaScriptVariantHelper.isMultiQNScope(context)) {
+ return MultimapBasedScope.createScope(parent, descriptions, false);
+ } else {
+ return MapBasedScope.createScope(parent, descriptions);
+ }
+ }
+
+ /**
+ * Convenience method for {@link #scopeFor(Iterable,Function,Function,IScope)}.
+ */
+ public IScope scopeFor(Iterable extends EObject> elements,
+ Function wrapper) {
+ return scopeFor(elements, wrapper, IScope.NULLSCOPE);
+ }
+
+ /**
+ * Convenience method for {@link #scopeFor(Iterable,Function,Function,IScope)}.
+ */
+ public IScope scopeFor(Iterable extends EObject> elements,
+ Function wrapper, IScope outer) {
+ return scopeFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER), wrapper, outer);
+ }
+
+ /**
+ * Similar to {@link Scopes#scopeFor(Iterable,Function,IScope)} but supports custom wrapping of the
+ * IEObjectDescriptions, for example to wrap them with error message providing subclasses such as
+ * {@link WrongStaticAccessDescription}. The wrapper can return the object description unchanged, create and return
+ * a new one or may return null to remove the corresponding object from the scope.
+ */
+ public IScope scopeFor(Iterable extends T> elements,
+ Function nameComputation,
+ Function wrapper, IScope outer) {
+ return new SimpleScope(outer,
+ Iterables.transform(Scopes.scopedElementsFor(elements, nameComputation), wrapper));
+ }
+}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.xtend b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.xtend
deleted file mode 100644
index 3975a05c70..0000000000
--- a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/scoping/utils/ScopesHelper.xtend
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Copyright (c) 2016 NumberFour AG.
- * 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:
- * NumberFour AG - Initial API and implementation
- */
-package org.eclipse.n4js.scoping.utils
-
-import com.google.common.base.Function
-import com.google.common.collect.Iterables
-import org.eclipse.emf.ecore.EObject
-import org.eclipse.xtext.naming.QualifiedName
-import org.eclipse.xtext.resource.IEObjectDescription
-import org.eclipse.xtext.scoping.IScope
-import org.eclipse.xtext.scoping.Scopes
-import org.eclipse.xtext.scoping.impl.SimpleScope
-import org.eclipse.xtext.util.SimpleAttributeResolver
-import com.google.inject.Inject
-import org.eclipse.n4js.validation.JavaScriptVariantHelper
-import org.eclipse.xtext.scoping.impl.MapBasedScope
-import org.eclipse.xtext.scoping.impl.MultimapBasedScope
-
-/**
- * Some utility methods, similar to xtext's {@link Scopes}.
- */
-public class ScopesHelper {
-
- @Inject
- private JavaScriptVariantHelper javaScriptVariantHelper;
-
- /**
- * Creates a map based scope for the given iterable of descriptions.
- *
- * @param context The context of the scope
- * @param descriptions The descriptions
- */
- def public IScope mapBasedScopeFor(EObject context, Iterable descriptions) {
- return mapBasedScopeFor(context, IScope.NULLSCOPE, descriptions);
- }
-
- /**
- * Creates a map based scope for the given iterable of descriptions.
- *
- * @param context The context of the scope
- * @param parent The parent scope
- * @param descriptions The descriptions
- */
- def public IScope mapBasedScopeFor(EObject context, IScope parent, Iterable descriptions) {
- if (javaScriptVariantHelper.isMultiQNScope(context)) {
- return MultimapBasedScope.createScope(parent, descriptions, false);
- } else {
- return MapBasedScope.createScope(parent, descriptions);
- }
- }
-
- /**
- * Convenience method for {@link #scopeFor(Iterable,Function,Function,IScope)}.
- */
- def public IScope scopeFor(Iterable extends EObject> elements,
- Function wrapper) {
- return scopeFor(elements, wrapper, IScope.NULLSCOPE);
- }
-
- /**
- * Convenience method for {@link #scopeFor(Iterable,Function,Function,IScope)}.
- */
- def public IScope scopeFor(Iterable extends EObject> elements,
- Function wrapper, IScope outer) {
- return scopeFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER), wrapper, outer);
- }
-
- /**
- * Similar to {@link Scopes#scopeFor(Iterable,Function,IScope)} but supports custom wrapping
- * of the IEObjectDescriptions, for example to wrap them with error message providing subclasses
- * such as {@link WrongStaticAccessDescription}. The wrapper can return the object description
- * unchanged, create and return a new one or may return null to remove the corresponding object
- * from the scope.
- */
- def public IScope scopeFor(Iterable extends T> elements,
- Function nameComputation,
- Function wrapper, IScope outer) {
- return new SimpleScope(outer,
- Iterables.transform(Scopes.scopedElementsFor(elements, nameComputation), wrapper));
- }
-}