use of org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method checkUnpairedAccessorFilling.
private void checkUnpairedAccessorFilling(MemberMatrix mm, N4ClassifierDefinition definition) {
if (definition.getDefinedType().isStaticPolyfill() && mm.hasMixedAccessorPair()) {
FieldAccessor ownedAccessor = (FieldAccessor) Iterables.getFirst(mm.owned(), null);
if (null == ownedAccessor) {
// Should not happen, a mixed accessor pair implies at least one owned member
return;
}
if (!(definition instanceof N4ClassDefinition)) {
// Non-class static polyfills aren't allowed. Validated somewhere else.
return;
}
TClass filledClass = MemberRedefinitionUtils.getFilledClass((N4ClassDefinition) definition);
if (null == filledClass) {
// Invalid static polyfill class. Validated somewhere else.
return;
}
// Iterate over all inherited members
SourceAwareIterator memberIterator = mm.actuallyInheritedAndMixedMembers();
while (memberIterator.hasNext()) {
TMember next = memberIterator.next();
ContainerType<?> containingType = next.getContainingType();
// Issue an error if the member isn't owned by the filled class
if (containingType != filledClass) {
messageMissingOwnedAccessor(ownedAccessor);
}
}
}
}
use of org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method constraints_41_AbstractClass.
/**
* Constraints 41 (Abstract Class)
*/
private boolean constraints_41_AbstractClass(TClassifier classifier, MemberCube memberCube) {
List<TMember> abstractMembers = null;
if (!classifier.isAbstract() && classifier instanceof TClass) {
for (Entry<NameStaticPair, MemberMatrix> entry : memberCube.entrySet()) {
MemberMatrix mm = entry.getValue();
MemberList<TMember> l = new MemberList<>();
Iterators.addAll(l, mm.actuallyInheritedAndMixedMembers());
for (SourceAwareIterator iter = mm.actuallyInheritedAndMixedMembers(); iter.hasNext(); ) {
TMember m = iter.next();
if (m.isAbstract()) {
if (abstractMembers == null) {
abstractMembers = new ArrayList<>();
}
abstractMembers.add(m);
}
}
}
}
if (abstractMembers != null) {
messageMissingImplementations(abstractMembers);
return false;
}
return true;
}
use of org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method constraints_69_Implementation.
/**
* Constraints 69: Implementation of Interface Members
*
* This method doesn't add issues for missing override annotations but adds the missing-annotation-members to the
* given collection.
*/
private void constraints_69_Implementation(MemberMatrix mm, Collection<TMember> membersMissingOverrideAnnotation) {
String missingAccessor = null;
List<TMember> missingAccessors = new MemberList<>();
List<TMember> conflictingMembers = new MemberList<>();
TClassifier currentClassifier = getCurrentClassifier();
// avoid multiple errors on a single element (but not on
Set<TMember> ownedErroneousMembers = null;
for (TMember m : mm.implemented()) {
if (mm.isConsumed(m)) {
// m is mixed in, so it exits and we do not need other tests
continue;
}
boolean bExistCompatibleMember = false;
boolean bExistCompatibleGetter = false;
boolean bExistCompatibleSetter = false;
for (SourceAwareIterator iter = mm.ownedConsumedInheritedImplemented(); iter.hasNext(); ) {
TMember m_ = iter.next();
if (ownedErroneousMembers != null && !iter.isOwnedMember()) {
// we found problems with owned members, we do not need more error messages.
break;
}
// short cut and avoid multiple errors for single member
if (m_ == m || ownedErroneousMembers != null && ownedErroneousMembers.contains(m_)) {
if (iter.isInheritedMember()) {
// consumed by super class and then inherited
bExistCompatibleMember = true;
}
// we do not break since we want to find possible consumption problems
continue;
}
// 1. m must be accessible and
// 2.a & 2.b: m_ must be implementation-compatible to m
OverrideCompatibilityResult compatibility = checkAccessibilityAndOverrideCompatibility(RedefinitionType.implemented, m_, m, !iter.isActualMember(), mm);
if (compatibility == OverrideCompatibilityResult.ACCESSOR_PAIR) {
continue;
} else if (compatibility == OverrideCompatibilityResult.ERROR) {
if (iter.isOwnedMember()) {
// do not skip other errors for owned members, usually accessor pairs
if (ownedErroneousMembers == null) {
ownedErroneousMembers = new HashSet<>();
}
ownedErroneousMembers.add(m_);
} else if (iter.isActualMember()) {
// error message already
return;
} else {
break;
}
} else if (iter.isActualMember()) {
// mark found implementor
if (m.isField()) {
if (m_.isGetter()) {
bExistCompatibleGetter = true;
} else if (m_.isSetter()) {
bExistCompatibleSetter = true;
} else {
bExistCompatibleMember = true;
}
} else {
bExistCompatibleMember = true;
}
// 1 & 2 declared overridden
if (!m_.isDeclaredOverride() && m_.getContainingType() == currentClassifier) {
membersMissingOverrideAnnotation.add(m_);
}
}
}
if (bExistCompatibleGetter != bExistCompatibleSetter) {
missingAccessor = bExistCompatibleGetter ? "setter" : "getter";
missingAccessors.add(m);
} else if (!bExistCompatibleMember && !(bExistCompatibleGetter && bExistCompatibleSetter)) {
conflictingMembers.add(m);
}
}
if (ownedErroneousMembers != null) {
// avoid consequential errors
return;
}
if (!conflictingMembers.isEmpty()) {
messageConflictingMixins(conflictingMembers);
} else if (!missingAccessors.isEmpty()) {
messageMissingAccessor(missingAccessor, missingAccessors);
}
}
use of org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method constraints_42_45_46_AbstractMember.
/**
* Constraints 42, 3 (Abstract Member)<br>
* Constraints 45, 4 (Extending Interfaces)<br>
* Constraints 46, 5 (Implementing Interfaces)
*
* This method doesn't add issues for missing override annotations but adds the missing-annotation-members to the
* given collection.
*/
private void constraints_42_45_46_AbstractMember(MemberMatrix mm, Map<ParameterizedTypeRef, MemberList<TMember>> nonAccessibleAbstractMembersBySuperTypeRef) {
N4ClassifierDefinition classifierDefinition = getCurrentClassifierDefinition();
TClassifier classifier = getCurrentClassifier();
TModule contextModule = EcoreUtil2.getContainerOfType(classifier, TModule.class);
for (SourceAwareIterator iter = mm.allMembers(); iter.hasNext(); ) {
TMember m = iter.next();
if (!iter.isOwnedMember() && m.isAbstract()) {
if (!memberVisibilityChecker.isVisibleWhenOverriding(contextModule, classifier, classifier, m)) {
Iterable<ParameterizedTypeRef> superTypeRefs = FindClassifierInHierarchyUtils.findSuperTypesWithMember(classifierDefinition, m);
for (ParameterizedTypeRef superTypeRef : superTypeRefs) {
MemberList<TMember> nonAccessible = nonAccessibleAbstractMembersBySuperTypeRef.get(superTypeRef);
if (nonAccessible == null) {
nonAccessible = new MemberList<>();
nonAccessibleAbstractMembersBySuperTypeRef.put(superTypeRef, nonAccessible);
}
nonAccessible.add(m);
}
}
}
}
}
use of org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method holdConstraints_68_Consumption.
/**
* Constraints 68: Consumption of Interface Members
*
* Returns false if an error occurred which is not solvable in current classifier (i.e., incompatible meta types).
*/
private boolean holdConstraints_68_Consumption(MemberMatrix mm) {
TClassifier currentType = getCurrentClassifier();
MemberList<TMember> consumedMembers = new MemberList<>(2);
for (TMember m : mm.implemented()) {
boolean consume = true;
for (SourceAwareIterator iter = mm.allMembers(); iter.hasNext(); ) {
TMember m_ = iter.next();
if (m_ == m && iter.isInterfaceMember()) {
// again. Thus, we only consume if both members stem from interfaces
continue;
}
// 1. meta type
if ((m.isMethod() && !m_.isMethod()) || (!m.isMethod() && !(m_.isAccessor() || m_.isField()))) {
if (iter.isInterfaceMember()) {
messageIncompatibleMembersToImplement(mm.implemented());
return false;
} else if (iter.isInheritedMember()) {
messageIncompatibleInheritedMembersToImplement(m_, mm.implemented());
return false;
} else {
return true;
}
}
// 2 (abstract/owned), 3 (visibility) and 4 (type):
boolean accessorPair = TypeUtils.isAccessorPair(m, m_);
if (!accessorPair) {
// 2. not abstract or owned
if ((!m_.isAbstract() || m_.getContainingType() == currentType)) {
consume = false;
break;
}
// 3. access modifier
if (AccessModifiers.less(m, m_)) {
consume = false;
break;
}
// 4. type
if (!m_.isSetter()) {
if (!isSubType(m, m_)) {
consume = false;
break;
}
}
if (m_.isSetter() || m_.isField()) {
if (!isSubType(m_, m)) {
consume = false;
break;
}
}
}
}
if (consume) {
if (!consumedMembers.contains(m)) {
// in case an interface is (indirectly) redundantly implemented
consumedMembers.add(m);
}
}
}
mm.markConsumed(consumedMembers);
return true;
}
Aggregations