use of org.eclipse.n4js.ts.types.TField in project n4js by eclipse.
the class N4JSMemberRedefinitionValidator method constraints_65_overrideCompatible.
/**
* Constraints 65 (Override Compatible) and relation overrideCompatible.
*
* @param m
* the overriding member
* @param s
* the overridden or implemented member
* @param consumptionConflict
* check override or implementation override, the latter usually stems from a consumption conflict (so
* that s did not get consumed in the first place)
* @param mm
* member matrix, only to improve error message
* @return true if m is override compatible to s. Note that false does not necessarily means that an error occurred,
* since e.g., a getter does not effect a setter
*/
private OverrideCompatibilityResult constraints_65_overrideCompatible(RedefinitionType redefinitionType, TMember m, TMember s, boolean consumptionConflict, MemberMatrix mm) {
// 1. name and static modifier are always equal here, so we do not have to check that again
// 2. meta type
boolean metaTypeCompatible = MemberRedefinitionUtils.isMetaTypeCompatible(m, s);
if (!metaTypeCompatible) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideMetaTypeIncompatible(redefinitionType, m, s, mm);
}
return OverrideCompatibilityResult.ERROR;
}
// 3. s not final
if (s.isFinal()) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideFinal(redefinitionType, m, s);
}
return OverrideCompatibilityResult.ERROR;
}
final boolean sIsField = s instanceof TField;
final boolean sIsSetter = s instanceof TSetter;
final boolean mIsField = m instanceof TField;
// 4. s not const
if (sIsField) {
// const only defined on TField & TStructuralField
TField sF = (TField) s;
if (sF.isConst()) {
// By GHOLD-186 const redefinition is allowed for const fields
if (!((mIsField) && ((TField) m).isConst())) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideConst(redefinitionType, m, sF);
}
return OverrideCompatibilityResult.ERROR;
}
}
}
// 5. must not override non-final/non-const field or setter with a @Final/const field
if (sIsField || sIsSetter) {
if (!s.isFinal() && !s.isConst()) {
if (mIsField && (m.isFinal() || m.isConst())) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideWithFinalOrConstField(redefinitionType, m, s);
}
return OverrideCompatibilityResult.ERROR;
}
}
}
// 6. abstract
if (m.isAbstract() && !s.isAbstract()) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideAbstract(redefinitionType, m, s);
}
return OverrideCompatibilityResult.ERROR;
}
// 7. type compatible
if (!m.isSetter() && !s.isSetter()) {
// in Method (including constructor), Getter, Field
Result<Boolean> result = isSubTypeResult(m, s);
if (result.failed()) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideMemberTypeConflict(redefinitionType, m, s, result, mm);
}
return OverrideCompatibilityResult.ERROR;
}
}
boolean sIsConst = false;
if (sIsField) {
sIsConst = ((TField) s).isConst();
}
if ((m.isSetter() || m.isField()) && !s.isGetter() && !sIsConst) {
Result<Boolean> result = isSubTypeResult(s, m);
if (result.failed()) {
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideMemberTypeConflict(redefinitionType, m, s, result, mm);
}
return OverrideCompatibilityResult.ERROR;
}
}
// 8.1 accessibility must not be reduced
if (AccessModifiers.checkedLess(m, s)) {
// fix modifiers in order to avoid strange behavior
if (!consumptionConflict) {
// avoid consequential errors
messageOverrideAccessibilityReduced(redefinitionType, m, s);
}
return OverrideCompatibilityResult.ERROR;
}
// 8.2 special accessibility handling of public@Internal and protected as they reduce each other
MemberAccessModifier fixedLeft = AccessModifiers.fixed(m);
MemberAccessModifier fixedRight = AccessModifiers.fixed(s);
if ((fixedLeft == MemberAccessModifier.PROTECTED && fixedRight == MemberAccessModifier.PUBLIC_INTERNAL) || (fixedLeft == MemberAccessModifier.PUBLIC_INTERNAL && fixedRight == MemberAccessModifier.PROTECTED)) {
messageOverrideAccessibilityReduced(redefinitionType, m, s);
return OverrideCompatibilityResult.ERROR;
}
return OverrideCompatibilityResult.COMPATIBLE;
}
use of org.eclipse.n4js.ts.types.TField in project n4js by eclipse.
the class FieldFactory method create.
@Override
public TField create(String name) {
TField field = TypesFactory.eINSTANCE.createTField();
field.setComposed(true);
TypeRef typeRef = getReturnTypeRef();
TypeUtils.setMemberTypeRef(field, typeRef);
field.setName(name);
field.setDeclaredFinal(isFinal());
field.setDeclaredMemberAccessModifier(getAccessability());
return field;
}
use of org.eclipse.n4js.ts.types.TField in project n4js by eclipse.
the class ConcreteMembersOrderedForTranspiler method create.
/**
* Returns a tuple of collections used by transpiler to generate interface or class members.
*/
public static ConcreteMembersOrderedForTranspiler create(ContainerTypesHelper containerTypesHelper, TClassifier type, Script context) {
MemberCollector collector = containerTypesHelper.fromContext(context);
List<TMember> concreteInheritedMembers = (type instanceof TClass) ? collector.inheritedMembers((TClass) type) : emptyList();
List<TMember> ownedAndMixedInConcreteMembers = collector.computeOwnedAndMixedInConcreteMembers(type);
List<AccessorTuple> concreteAccessorTuples = getConcreteFieldAccessors(ownedAndMixedInConcreteMembers, concreteInheritedMembers);
MemberList<TField> fieldsOverridingAccessors = getFieldsOverridingAccessor(ownedAndMixedInConcreteMembers, concreteInheritedMembers);
// compute the list of mixed in fields, which do not override any Accessor (handled separately)
MemberList<TField> fieldsPurelyMixedInNotOverridingAccessor = new MemberList<>();
fieldsPurelyMixedInNotOverridingAccessor.addAll(ownedAndMixedInConcreteMembers.stream().filter(it -> it instanceof TField && // must stem from different type
it.getContainingType() != type).map(it -> (TField) it).filter(// remove the ones overriding get/set
it -> !fieldsOverridingAccessors.contains(it)).collect(Collectors.toList()));
return new ConcreteMembersOrderedForTranspiler(concreteInheritedMembers, ownedAndMixedInConcreteMembers, concreteAccessorTuples, fieldsOverridingAccessors, fieldsPurelyMixedInNotOverridingAccessor);
}
use of org.eclipse.n4js.ts.types.TField in project n4js by eclipse.
the class ConcreteMembersOrderedForTranspiler method mapToAccessorTuples.
/**
* Maps getters and setters to {@link AccessorTuple}s, used to generate proper setters-getters-pairs for property.
* The passed maps may be changed!
*
* @param getters
* list of getters
* @param fields
* list of fields
* @param io_setters
* map with owned getters, this map may be changed by this method
* @param io_inheritedGetters
* map with inherited getters, this map may be changed by this method
* @param io_inheritedSetters
* map with inherited getters, this map may be changed by this method
* @return list of accessor tuples.
*/
private static List<AccessorTuple> mapToAccessorTuples(Iterable<TGetter> getters, Map<NameStaticPair, TSetter> io_setters, Iterable<TField> fields, Map<NameStaticPair, TGetter> io_inheritedGetters, Map<NameStaticPair, TSetter> io_inheritedSetters) {
List<AccessorTuple> tuples = new ArrayList<>();
// add getters (alone & with corresponding setter)
for (TGetter getter : getters) {
AccessorTuple tuple = new AccessorTuple(getter.getName(), getter.isStatic());
tuple.setGetter(getter);
NameStaticPair nsp = NameStaticPair.of(getter);
// do not handle the thing twice
tuple.setSetter(io_setters.remove(nsp));
if (tuple.getSetter() == null) {
tuple.setInheritedSetter(io_inheritedSetters.remove(nsp));
}
tuples.add(tuple);
}
// add setters w/o getter:
for (TSetter setter : io_setters.values()) {
AccessorTuple tuple = new AccessorTuple(setter.getName(), setter.isStatic());
NameStaticPair nsp = NameStaticPair.of(setter);
tuple.setSetter(setter);
tuple.setInheritedGetter(io_inheritedGetters.remove(nsp));
tuples.add(tuple);
}
// remove the inherited references - the field will overwrite them.
for (TField field : fields) {
NameStaticPair nsp = NameStaticPair.of(field);
io_inheritedSetters.remove(nsp);
io_inheritedGetters.remove(nsp);
}
// find getters/setters defined in interfaces which need to be combined:
for (TSetter inhSetter : io_inheritedSetters.values()) {
TGetter inhGetter = io_inheritedGetters.remove(NameStaticPair.of(inhSetter));
if (inhGetter != null && inhSetter.getContainingType() != inhGetter.getContainingType() && (inhSetter.getContainingType() instanceof TInterface || inhGetter.getContainingType() instanceof TInterface)) {
// getter & setter are inherited from different types.
AccessorTuple tuple = new AccessorTuple(inhSetter.getName(), inhSetter.isStatic());
tuple.setInheritedGetter(inhGetter);
tuple.setInheritedSetter(inhSetter);
tuples.add(tuple);
}
}
return tuples;
}
use of org.eclipse.n4js.ts.types.TField in project n4js by eclipse.
the class ConcreteMembersOrderedForTranspiler method getConcreteFieldAccessors.
/**
* Helper method, returns all concrete field accessors as tuples of the given classifier, which may even contain
* fields if they override concrete getters or setter. Since getter/setters can only be defined as pairs, in case of
* single owned getter with inherited setter, a delegate is created for the setter (and vice versa).
*/
private static List<AccessorTuple> getConcreteFieldAccessors(List<TMember> ownedAndMixedInConcreteMember, List<TMember> concreteInheritedMembers) {
Set<TField> ownedAndMixedInFields = new HashSet<>();
Set<TGetter> ownedAndMixedInGetters = new HashSet<>();
Map<NameStaticPair, TSetter> ownedAndMixedInSetters = new HashMap<>();
for (TMember m : ownedAndMixedInConcreteMember) {
if (m instanceof TField) {
ownedAndMixedInFields.add((TField) m);
} else if (m instanceof TGetter) {
ownedAndMixedInGetters.add((TGetter) m);
} else if (m instanceof TSetter) {
ownedAndMixedInSetters.put(NameStaticPair.of(m), (TSetter) m);
}
}
Map<NameStaticPair, TGetter> inheritedGetters = new HashMap<>();
Map<NameStaticPair, TSetter> inheritedSetters = new HashMap<>();
for (TMember m : concreteInheritedMembers) {
if (m instanceof TGetter) {
if (!ownedAndMixedInGetters.contains(m)) {
inheritedGetters.put(NameStaticPair.of(m), (TGetter) m);
}
} else if (m instanceof TSetter) {
NameStaticPair nsp = NameStaticPair.of(m);
if (ownedAndMixedInSetters.get(nsp) != m) {
inheritedSetters.put(nsp, (TSetter) m);
}
}
}
List<AccessorTuple> ownedOrMixedInAccessorTouples = mapToAccessorTuples(ownedAndMixedInGetters, ownedAndMixedInSetters, ownedAndMixedInFields, inheritedGetters, inheritedSetters);
return ownedOrMixedInAccessorTouples;
}
Aggregations