diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.java b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.java
new file mode 100644
index 0000000000..2ad81b6aad
--- /dev/null
+++ b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.java
@@ -0,0 +1,226 @@
+/**
+ * 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.validation.validators;
+
+import static org.eclipse.xtext.xbase.lib.IterableExtensions.exists;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.n4js.smith.Measurement;
+import org.eclipse.n4js.smith.N4JSDataCollectors;
+import org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef;
+import org.eclipse.n4js.ts.typeRefs.TypeRef;
+import org.eclipse.n4js.ts.types.ContainerType;
+import org.eclipse.n4js.ts.types.PrimitiveType;
+import org.eclipse.n4js.ts.types.TClass;
+import org.eclipse.n4js.ts.types.TClassifier;
+import org.eclipse.n4js.ts.types.TInterface;
+import org.eclipse.n4js.ts.types.TMember;
+import org.eclipse.n4js.ts.types.Type;
+import org.eclipse.n4js.types.utils.TypeUtils;
+import org.eclipse.n4js.typesystem.utils.AbstractCompleteHierarchyTraverser;
+import org.eclipse.n4js.typesystem.utils.RuleEnvironment;
+import org.eclipse.n4js.typesystem.utils.RuleEnvironmentExtensions;
+import org.eclipse.n4js.utils.DeclMergingHelper;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+
+/**
+ * Collects all members, including inherited members, of a type and omits some members overridden in the type hierarchy.
+ * That is, members overridden in the type hierarchy are removed and replaced by the overridden members. However, this
+ * is done lazily, that is not all cases are considered, as the result is further validated anyway. That is,
+ *
+ * - data fields and corresponding accessors are not recognized to public each other
+ *
- methods (and fields) inherited from interfaces are all added and not filtered.
+ *
- private members are added to result (which is required for validation: cannot public private member etc.)
+ *
+ * Thus, this collector should only be used for validation purposes.
+ */
+
+public class LazyOverrideAwareMemberCollector {
+ @Inject
+ private DeclMergingHelper declMergingHelper;
+
+ /**
+ * Collects all members, including owned members and members defined in implicit super types.
+ */
+ public List collectAllMembers(ContainerType> type) {
+ return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, true, false).getResult();
+ }
+
+ /**
+ * Collects all inherited members, including members defined in implicit super types; owned members are omitted.
+ */
+ public List collectAllInheritedMembers(ContainerType> type) {
+ return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, true, true).getResult();
+ }
+
+ /**
+ * Collects all declared members, including owned members; members defined in implicit super types are omitted.
+ */
+ public List collectAllDeclaredMembers(ContainerType> type) {
+ return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, false, false).getResult();
+ }
+
+ /**
+ * Collects all declared inherited members; owned members and members defined in implicit super types are omitted.
+ */
+ public List collectAllDeclaredInheritedMembers(ContainerType> type) {
+ return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, false, true).getResult();
+ }
+
+ static class LazyOverrideAwareMemberCollectorX extends AbstractCompleteHierarchyTraverser> {
+
+ boolean includeImplicitSuperTypes;
+
+ private List result;
+ private final RuleEnvironment G;
+
+ boolean onlyInheritedMembers;
+
+ /**
+ * Creates a new collector with optional support for implicit super types, better use static helper methods.
+ *
+ * @param type
+ * the base type. Must be contained in a resource set if includeImplicitSuperTypes
is
+ * set to true
.
+ * @param includeImplicitSuperTypes
+ * if true also members of implicit super types will be collected; otherwise only members of declared
+ * super types are included.
+ * @param onlyInheritedMembers
+ * if true, owned members of type are ignore, that is only inherited members are collected
+ * @throws IllegalArgumentException
+ * if includeImplicitSuperTypes
is set to true
and type
is
+ * not contained in a properly initialized N4JS resource set.
+ */
+ private LazyOverrideAwareMemberCollectorX(ContainerType> type, DeclMergingHelper declMergingHelper,
+ boolean includeImplicitSuperTypes, boolean onlyInheritedMembers) {
+ super(type, declMergingHelper);
+ this.onlyInheritedMembers = onlyInheritedMembers;
+ this.includeImplicitSuperTypes = includeImplicitSuperTypes;
+ this.result = createResultInstance();
+ this.G = (includeImplicitSuperTypes) ? RuleEnvironmentExtensions.newRuleEnvironment(type) : null;
+ }
+
+ @Override
+ public Measurement getMeasurement() {
+ return N4JSDataCollectors.dcTHT_LazyOverrideAwareMemberCollectorX
+ .getMeasurementIfInactive("HierarchyTraverser");
+ }
+
+ public List createResultInstance() {
+ return Lists.newLinkedList();
+ }
+
+ @Override
+ public List doGetResult() {
+ return result;
+ }
+
+ @Override
+ public void doProcess(ContainerType> type) {
+ if (type instanceof TClassifier) {
+ EList ownedMembers = ((TClassifier) type).getOwnedMembers();
+ result.addAll(ownedMembers);
+ }
+ }
+
+ @Override
+ public void doProcess(PrimitiveType currentType) {
+ // nothing to do in this case
+ }
+
+ protected void processAndReplace(TClassifier type) {
+ EList ownedMembers = type.getOwnedMembers();
+ Iterator iterInherited = result.iterator();
+ while (iterInherited.hasNext()) {
+ TMember inherited = iterInherited.next();
+ if (exists(ownedMembers, m -> Objects.equals(m.getName(), inherited.getName())
+ && m.getMemberType() == inherited.getMemberType() && m.isStatic() == inherited.isStatic())) {
+ iterInherited.remove();
+ }
+ }
+ result.addAll(ownedMembers);
+ }
+
+ /**
+ * Does not add owned members and add inherited members overridden aware.
+ */
+ @Override
+ public boolean visitTClass(ParameterizedTypeRef typeRef, TClass object) {
+ List parentResult = result;
+ if (object != bottomType) {
+ result = createResultInstance();
+ }
+
+ // add and merge
+ doSwitchTypeRefs(getSuperTypes(object));
+ doSwitchTypeRefs(object.getImplementedInterfaceRefs());
+
+ // add and replace
+ if (!onlyInheritedMembers || object != bottomType) { // do not add
+ processAndReplace(object); // ownedMembers
+ }
+
+ if (parentResult != result) {
+ parentResult.addAll(result); // merge
+ result = parentResult;
+ }
+
+ return Boolean.FALSE;
+ }
+
+ /**
+ * Does not add owned members and add inherited members overridden aware.
+ */
+ @Override
+ public boolean visitTInterface(ParameterizedTypeRef typeRef, TInterface object) {
+ List parentResult = result;
+ if (object != bottomType) {
+ result = createResultInstance();
+ }
+
+ doSwitchTypeRefs(object.getSuperInterfaceRefs());
+ doSwitchTypeRefs(object.getSuperInterfaceRefs());
+ if (!onlyInheritedMembers || object != bottomType) { // do not add
+ processAndReplace(object);
+ }
+
+ if (parentResult != result) {
+ parentResult.addAll(result); // merge
+ result = parentResult;
+ }
+
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public List getImplicitSuperTypes(Type t) {
+ if (includeImplicitSuperTypes) {
+ List implSuperTypeRefs = new ArrayList<>();
+ for (TypeRef currTypeRef : RuleEnvironmentExtensions.collectAllImplicitSuperTypes(G,
+ TypeUtils.createTypeRef(t))) {
+ implSuperTypeRefs.add((ParameterizedTypeRef) currTypeRef); // they should all be
+ // ParameterizedTypeRefs
+ }
+ return implSuperTypeRefs;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.xtend b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.xtend
deleted file mode 100644
index 7168551693..0000000000
--- a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/LazyOverrideAwareMemberCollector.xtend
+++ /dev/null
@@ -1,216 +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.validation.validators
-
-import com.google.common.collect.Lists
-import java.util.ArrayList
-import java.util.Collections
-import java.util.List
-import org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef
-import org.eclipse.n4js.ts.typeRefs.TypeRef
-import org.eclipse.n4js.ts.types.ContainerType
-import org.eclipse.n4js.ts.types.PrimitiveType
-import org.eclipse.n4js.ts.types.TClass
-import org.eclipse.n4js.ts.types.TClassifier
-import org.eclipse.n4js.ts.types.TInterface
-import org.eclipse.n4js.ts.types.TMember
-import org.eclipse.n4js.ts.types.Type
-import org.eclipse.n4js.types.utils.TypeUtils
-import org.eclipse.n4js.typesystem.utils.AbstractCompleteHierarchyTraverser
-import org.eclipse.n4js.typesystem.utils.RuleEnvironment
-import org.eclipse.n4js.typesystem.utils.RuleEnvironmentExtensions
-import org.eclipse.n4js.utils.DeclMergingHelper
-import com.google.inject.Inject
-import org.eclipse.n4js.smith.N4JSDataCollectors
-import org.eclipse.n4js.smith.Measurement
-
-/**
- * Collects all members, including inherited members, of a type and omits some members overridden in the type hierarchy.
- * That is, members overridden in the type hierarchy are removed and replaced by the overridden members. However,
- * this is done lazily, that is not all cases are considered, as the result is further validated anyway.
- * That is,
- *
- * - data fields and corresponding accessors are not recognized to override each other
- *
- methods (and fields) inherited from interfaces are all added and not filtered.
- *
- private members are added to result (which is required for validation: cannot override private member etc.)
- *
- * Thus, this collector should only be used for validation purposes.
- */
-
-public class LazyOverrideAwareMemberCollector {
- @Inject
- private DeclMergingHelper declMergingHelper;
-
-
- /**
- * Collects all members, including owned members and members defined in implicit super types.
- */
- def List collectAllMembers(ContainerType> type) {
- return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, true, false).getResult();
- }
-
- /**
- * Collects all inherited members, including members defined in implicit super types; owned members are omitted.
- */
- def List collectAllInheritedMembers(ContainerType> type) {
- return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, true, true).getResult();
- }
-
- /**
- * Collects all declared members, including owned members; members defined in implicit super types are omitted.
- */
- def List collectAllDeclaredMembers(ContainerType> type) {
- return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, false, false).getResult();
- }
-
- /**
- * Collects all declared inherited members; owned members and members defined in implicit super types are omitted.
- */
- def List collectAllDeclaredInheritedMembers(ContainerType> type) {
- return new LazyOverrideAwareMemberCollectorX(type, declMergingHelper, false, true).getResult();
- }
-
- static class LazyOverrideAwareMemberCollectorX extends AbstractCompleteHierarchyTraverser> {
-
- val boolean includeImplicitSuperTypes;
-
- private var List result;
- private val RuleEnvironment G;
-
- val boolean onlyInheritedMembers
-
-
- /**
- * Creates a new collector with optional support for implicit super types, better use static helper methods.
- *
- * @param type
- * the base type. Must be contained in a resource set if includeImplicitSuperTypes
is set to
- * true
.
- * @param includeImplicitSuperTypes
- * if true also members of implicit super types will be collected; otherwise only members of declared
- * super types are included.
- * @param onlyInheritedMembers
- * if true, owned members of type are ignore, that is only inherited members are collected
- * @throws IllegalArgumentException
- * if includeImplicitSuperTypes
is set to true
and type
is not
- * contained in a properly initialized N4JS resource set.
- */
- private new(ContainerType> type, DeclMergingHelper declMergingHelper, boolean includeImplicitSuperTypes, boolean onlyInheritedMembers) {
- super(type, declMergingHelper);
- this.onlyInheritedMembers = onlyInheritedMembers;
- this.includeImplicitSuperTypes = includeImplicitSuperTypes;
- result = createResultInstance();
- G = if ( includeImplicitSuperTypes) RuleEnvironmentExtensions.newRuleEnvironment(type) else null;
- }
-
- override Measurement getMeasurement() {
- return N4JSDataCollectors.dcTHT_LazyOverrideAwareMemberCollectorX.getMeasurementIfInactive("HierarchyTraverser");
- }
-
- def List createResultInstance() {
- return Lists.newLinkedList()
- }
-
- override protected List doGetResult() {
- return result;
- }
-
- override protected void doProcess(ContainerType> type) {
- if (type instanceof TClassifier) {
- val ownedMembers = type.getOwnedMembers()
- result.addAll(ownedMembers);
- }
- }
-
- override protected doProcess(PrimitiveType currentType) {
- // nothing to do in this case
- }
-
- def protected processAndReplace(TClassifier type) {
- val ownedMembers = type.getOwnedMembers()
- val iterInherited = result.iterator
- while (iterInherited.hasNext()) {
- val inherited = iterInherited.next;
- if (ownedMembers.exists[
- name==inherited.name && memberType===inherited.memberType && static===inherited.static
- ]) {
- iterInherited.remove
- }
- }
- result.addAll(ownedMembers)
- }
-
-
- /**
- * Does not add owned members and add inherited members overridden aware.
- */
- override boolean visitTClass(ParameterizedTypeRef typeRef, TClass object) {
- val parentResult = result
- if (object!==bottomType) {
- result = createResultInstance();
- }
-
- // add and merge
- doSwitchTypeRefs(getSuperTypes(object));
- doSwitchTypeRefs(object.getImplementedInterfaceRefs());
-
- // add and replace
- if (!onlyInheritedMembers || object!=bottomType) { // do not add
- processAndReplace(object); // ownedMembers
- }
-
- if (parentResult!==result) {
- parentResult.addAll(result); // merge
- result = parentResult;
- }
-
- return Boolean.FALSE;
- }
-
-
-
- /**
- * Does not add owned members and add inherited members overridden aware.
- */
- override public boolean visitTInterface(ParameterizedTypeRef typeRef, TInterface object) {
- val parentResult = result
- if (object!==bottomType) {
- result = createResultInstance();
- }
-
- doSwitchTypeRefs(object.getSuperInterfaceRefs());
- doSwitchTypeRefs(object.getSuperInterfaceRefs());
- if (!onlyInheritedMembers || object!=bottomType) { // do not add
- processAndReplace(object);
- }
-
- if (parentResult!==result) {
- parentResult.addAll(result); // merge
- result = parentResult;
- }
-
- return Boolean.FALSE;
- }
-
-
- override protected List getImplicitSuperTypes(Type t) {
- if (includeImplicitSuperTypes) {
- val List implSuperTypeRefs = new ArrayList();
- for (TypeRef currTypeRef : RuleEnvironmentExtensions.collectAllImplicitSuperTypes(G,
- TypeUtils.createTypeRef(t)))
- implSuperTypeRefs.add(currTypeRef as ParameterizedTypeRef); // they should all be ParameterizedTypeRefs
- return implSuperTypeRefs;
- }
- else
- return Collections.emptyList();
- }
- }
-}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.java b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.java
new file mode 100644
index 0000000000..8259209e90
--- /dev/null
+++ b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.java
@@ -0,0 +1,72 @@
+/**
+ * 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.validation.validators;
+
+import static org.eclipse.n4js.validation.IssueCodes.THIRD_PARTY_BABEL_LET_CONST_IN_FUN_EXPR;
+
+import java.util.Objects;
+
+import org.eclipse.n4js.n4JS.FunctionExpression;
+import org.eclipse.n4js.n4JS.N4JSPackage;
+import org.eclipse.n4js.n4JS.Statement;
+import org.eclipse.n4js.n4JS.VariableDeclaration;
+import org.eclipse.n4js.n4JS.VariableStatement;
+import org.eclipse.n4js.n4JS.VariableStatementKeyword;
+import org.eclipse.n4js.validation.AbstractN4JSDeclarativeValidator;
+import org.eclipse.xtext.validation.Check;
+import org.eclipse.xtext.validation.EValidatorRegistrar;
+
+/**
+ * Validations that implement warnings unrelated to the N4JS language. They hint towards limitations and problems in
+ * third-party tools that are commonly used together with N4JS (e.g. Babel).
+ */
+public class ThirdPartyValidator extends AbstractN4JSDeclarativeValidator {
+
+ /**
+ * NEEEDED
+ *
+ * when removed check methods will be called twice once by N4JSValidator, and once by
+ * AbstractDeclarativeN4JSValidator
+ */
+ @Override
+ public void register(EValidatorRegistrar registrar) {
+ // nop
+ }
+
+ /**
+ * Adds warning for Babel issue #6302.
+ *
+ * This can be removed once the corresponding test file compiles without errors in Babel:
+ * {@code /org.eclipse.n4js.spec.tests/xpect-tests/Others/ThirdParty_Babel_LetConstInFunctionExpression.n4js.xt}.
+ */
+ @Check
+ public void checkLetConstInFunctionExpression(FunctionExpression funExpr) {
+ String funName = funExpr.getName();
+ if (funName != null) {
+ // only interested in top-level statements of the body
+ for (Statement stmnt : funExpr.getBody().getStatements()) {
+ if (stmnt instanceof VariableStatement) {
+ VariableStatement vs = (VariableStatement) stmnt;
+ if (vs.getVarStmtKeyword() == VariableStatementKeyword.LET // only interested in let/const
+ || vs.getVarStmtKeyword() == VariableStatementKeyword.CONST) {
+
+ for (VariableDeclaration varDecl : vs.getVarDecl()) {
+ if (Objects.equals(varDecl.getName(), funName)) {
+ addIssue(varDecl, N4JSPackage.eINSTANCE.getAbstractVariable_Name(),
+ THIRD_PARTY_BABEL_LET_CONST_IN_FUN_EXPR.toIssueItem());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.xtend b/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.xtend
deleted file mode 100644
index 447b7ae056..0000000000
--- a/plugins/org.eclipse.n4js/src/org/eclipse/n4js/validation/validators/ThirdPartyValidator.xtend
+++ /dev/null
@@ -1,63 +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.validation.validators
-
-import org.eclipse.n4js.n4JS.FunctionExpression
-import org.eclipse.n4js.n4JS.N4JSPackage
-import org.eclipse.n4js.n4JS.VariableStatement
-import org.eclipse.n4js.n4JS.VariableStatementKeyword
-import org.eclipse.n4js.validation.AbstractN4JSDeclarativeValidator
-import org.eclipse.xtext.validation.Check
-import org.eclipse.xtext.validation.EValidatorRegistrar
-
-import static org.eclipse.n4js.validation.IssueCodes.*
-
-/**
- * Validations that implement warnings unrelated to the N4JS language. They hint towards limitations and problems in
- * third-party tools that are commonly used together with N4JS (e.g. Babel).
- */
-class ThirdPartyValidator extends AbstractN4JSDeclarativeValidator {
-
- /**
- * NEEEDED
- *
- * when removed check methods will be called twice once by N4JSValidator, and once by
- * AbstractDeclarativeN4JSValidator
- */
- override register(EValidatorRegistrar registrar) {
- // nop
- }
-
- /**
- * Adds warning for Babel issue #6302.
- *
- * This can be removed once the corresponding test file compiles without errors in Babel:
- * {@code /org.eclipse.n4js.spec.tests/xpect-tests/Others/ThirdParty_Babel_LetConstInFunctionExpression.n4js.xt}.
- */
- @Check
- def void checkLetConstInFunctionExpression(FunctionExpression funExpr) {
- val funName = funExpr.name;
- if (funName !== null) {
- for (stmnt : funExpr.body.statements) { // only interested in top-level statements of the body
- if (stmnt instanceof VariableStatement) {
- if (stmnt.varStmtKeyword === VariableStatementKeyword.LET // only interested in let/const
- || stmnt.varStmtKeyword === VariableStatementKeyword.CONST) {
- for (varDecl : stmnt.varDecl) {
- if (varDecl.name == funName) {
- addIssue(varDecl, N4JSPackage.eINSTANCE.abstractVariable_Name, THIRD_PARTY_BABEL_LET_CONST_IN_FUN_EXPR.toIssueItem());
- }
- }
- }
- }
- }
- }
- }
-}