use of org.eclipse.n4js.ts.types.TClassifier in project n4js by eclipse.
the class ProjectCompareHelper method internalCompareApiImpl.
private ProjectCompareResult internalCompareApiImpl(ProjectComparisonEntry entry, int implIdx) {
if (!entry.isElementEntry())
// not an entry for an EObject element -> never report differences
return ProjectCompareResult.equal();
final int implCount = entry.getImplCount();
if (implIdx < 0 || implIdx >= implCount)
// implementation index out of range -> never report differences
return ProjectCompareResult.equal();
// compare implementation to API
final EObject api = entry.getElementAPI();
final EObject impl = entry.getElementImpl()[implIdx];
// special case: no API
if (api == null) {
if (impl != null)
return ProjectCompareResult.compliant();
else
return ProjectCompareResult.equal();
}
// special case: no impl
if (impl == null) {
// note: we know api!=null because of above check
return ProjectCompareResult.error("missing implementation");
}
// accessibility-based compare:
if (api instanceof TMember && impl instanceof TMember) {
// order important: check for member before type!
if (AccessModifiers.less((TMember) impl, (TMember) api))
return ProjectCompareResult.error("reduced visibility");
} else if (api instanceof Type && impl instanceof Type) {
final MemberAccessModifier apiAcc = AccessModifiers.toMemberModifier((Type) api);
final MemberAccessModifier implAcc = AccessModifiers.toMemberModifier((Type) impl);
if (AccessModifiers.less(implAcc, apiAcc))
return ProjectCompareResult.error("reduced visibility");
}
ImplToApiReplacementProvider typeReplacementProvider = new ImplToApiReplacementProvider(entry.getRoot());
// subtype-based compare:
if (api instanceof TMember && impl instanceof TMember) {
final TMember apiMember = (TMember) api;
final TMember implMember = (TMember) impl;
if (apiMember instanceof TField) {
boolean bAPIProvidesInitializer = PROVIDES_INITIALZER.hasAnnotation(apiMember);
if (bAPIProvidesInitializer && !hasInitializer(impl)) {
if (bAPIProvidesInitializer) {
return ProjectCompareResult.error("no initializer in implementation but @" + PROVIDES_INITIALZER.name + " in API");
} else {
return ProjectCompareResult.error("initializer in implementation but no @" + PROVIDES_INITIALZER.name + " in API)");
}
}
} else {
// Method or accessor
boolean bAPIProvidesDefImpl = PROVIDES_DEFAULT_IMPLEMENTATION.hasAnnotation(apiMember);
if ((bAPIProvidesDefImpl != hasBody(impl)) && apiMember.eContainer() instanceof TInterface) {
if (bAPIProvidesDefImpl) {
return ProjectCompareResult.error("no body in implementation but @" + PROVIDES_DEFAULT_IMPLEMENTATION.name + " in API");
} else {
return ProjectCompareResult.error("body in implementation but no @" + PROVIDES_DEFAULT_IMPLEMENTATION.name + " in API");
}
}
}
final TypeRef context = TypeUtils.createTypeRef((Type) api.eContainer());
final TypeRef typeApi = typeSystem.tau(apiMember, context);
final TypeRef typeImpl = typeSystem.tau(implMember, context);
final RuleEnvironment G = RuleEnvironmentExtensions.newRuleEnvironment(api);
RuleEnvironmentExtensions.setTypeReplacement(G, typeReplacementProvider);
final Result<Boolean> implSubtypeApi = typeSystem.subtype(G, typeImpl, typeApi);
final Result<Boolean> apiSubtypeImpl = typeSystem.subtype(G, typeApi, typeImpl);
final boolean isImplSubtypeApi = !implSubtypeApi.failed();
final boolean isApiSubtypeImpl = !apiSubtypeImpl.failed();
final boolean isEqualType = isImplSubtypeApi && isApiSubtypeImpl;
if (!isEqualType) {
if (isImplSubtypeApi)
// not equal but at least compliant
return ProjectCompareResult.compliant();
else {
final String msg = implSubtypeApi.getRuleFailedException().getLocalizedMessage();
// not even compliant
return ProjectCompareResult.error(msg);
}
}
if (isSpecialCaseOfHiddenMethodDiff(api, impl)) {
// not equal but at least compliant
return ProjectCompareResult.compliant();
}
// all fine
return ProjectCompareResult.equal();
}
// classifier compare
if (api instanceof TClassifier && impl instanceof TClassifier) {
TClassifier apiClassifier = (TClassifier) api;
TClassifier implClassifier = (TClassifier) impl;
EList<TypeVariable> apiTypeVars = apiClassifier.getTypeVars();
EList<TypeVariable> implTypeVars = implClassifier.getTypeVars();
// check for number of type variables
if (apiTypeVars.size() != implTypeVars.size()) {
return ProjectCompareResult.error("the number of type variables doesn't match");
}
final RuleEnvironment ruleEnvironment = RuleEnvironmentExtensions.newRuleEnvironment(api);
RuleEnvironmentExtensions.setTypeReplacement(ruleEnvironment, typeReplacementProvider);
// check for upper bound compatibility
for (int i = 0; i < apiTypeVars.size(); i++) {
TypeVariable apiTypeVar = apiTypeVars.get(i);
TypeVariable implTypeVar = implTypeVars.get(i);
TypeRef apiDeclaredUpperBound = apiTypeVar.getDeclaredUpperBound();
TypeRef implDeclaredUpperBound = implTypeVar.getDeclaredUpperBound();
if ((apiDeclaredUpperBound != null) != (implDeclaredUpperBound != null) || (apiDeclaredUpperBound != null && implDeclaredUpperBound != null && !typeSystem.equaltypeSucceeded(ruleEnvironment, apiDeclaredUpperBound, implDeclaredUpperBound))) {
return ProjectCompareResult.error(String.format("the upper bound of type variable %s isn't compatible with the API", implTypeVar.getName()));
}
}
return ProjectCompareResult.equal();
}
// text-based compare:
// always compare with API
final String textApi = entry.getTextAPI();
final String textImpl = entry.getTextImpl(implIdx);
final boolean isEqual = textApi != null ? textApi.equals(textImpl) : textImpl == null;
if (!isEqual)
return ProjectCompareResult.error(textImpl + " is not equal to " + textApi);
return ProjectCompareResult.equal();
}
use of org.eclipse.n4js.ts.types.TClassifier in project n4js by eclipse.
the class VisibilityAwareCtorScope method wrapFilteredDescription.
@Override
protected IEObjectDescriptionWithError wrapFilteredDescription(IEObjectDescription originalDescr) {
EObject proxyOrInstance = originalDescr.getEObjectOrProxy();
// The cast to TClassifier always works (see the method isAccepted below).
TClassifier ctorClassifier = (TClassifier) proxyOrInstance;
return new InvisibleCtorDescription(originalDescr, ctorClassifier);
}
use of org.eclipse.n4js.ts.types.TClassifier in project n4js by eclipse.
the class N4JSScopingConsumableMethodsDiagnosis method diagnose.
@Override
DiagnosticMessage diagnose(QualifiedName name, ParameterizedPropertyAccessExpression propertyAccess) {
// determine containing member declaration and classifier definition
N4MemberDeclaration containingMemberDeclaration = EcoreUtil2.getContainerOfType(propertyAccess, N4MemberDeclaration.class);
N4ClassifierDefinition classifierDefinition = EcoreUtil2.getContainerOfType(containingMemberDeclaration, N4ClassifierDefinition.class);
// if ancestors present and non-static context (no super in static context)
if (containingMemberDeclaration != null && !containingMemberDeclaration.isStatic() && classifierDefinition != null) {
// Get candidate methods
MemberList<TMember>.MemberIterable<TMethod> methods = containerTypesHelper.fromContext(propertyAccess).membersOfImplementedInterfacesForConsumption((TClassifier) classifierDefinition.getDefinedType()).methods();
boolean hasMethod = methods.stream().filter(// Filter for non-static non-abstract methods
m -> !m.isHasNoBody() && !m.isStatic()).anyMatch(m -> m.getName().equals(name.toString()));
if (hasMethod) {
return createMessage(IssueCodes.CLF_CANNOT_REFER_TO_DEFAULT_METHOD_WITH_SUPER, IssueCodes.getMessageForCLF_CANNOT_REFER_TO_DEFAULT_METHOD_WITH_SUPER());
}
}
return null;
}
use of org.eclipse.n4js.ts.types.TClassifier in project n4js by eclipse.
the class MissingApiMembersForTranspiler method create.
/**
* Returns a tuple of collections used by transpiler to generate interface or class members.
*/
public static MissingApiMembersForTranspiler create(ContainerTypesHelper containerTypesHelper, ScriptApiTracker apiTracker, TClassifier type, ConcreteMembersOrderedForTranspiler cmoft, Script context) {
MemberCollector collector = containerTypesHelper.fromContext(context);
// IDE-1510 create missing API-methods here.
MemberList<TMethod> missingApiMethods = new MemberList<>();
if (type instanceof TClass) {
List<TMethod> c = apiTracker.computeMissingApiMethods((TClass) type, context);
missingApiMethods.addAll(c);
List<VirtualApiTMethod> missingAPIfromInheritance = apiTracker.computeMethodDiff((TClass) type, collector, cmoft.ownedAndMixedInConcreteMembers, missingApiMethods);
missingApiMethods.addAll(missingAPIfromInheritance);
}
if (type instanceof TInterface) {
List<TMethod> c = apiTracker.computeMissingApiMethods((TInterface) type, context);
missingApiMethods.addAll(c);
}
// IDE-1510 create missing API-fields here.
List<AccessorTuple> missingApiAccessorTuples = new ArrayList<>();
{
List<AccessorTuple> computedMissingApiGetterSetter = apiTracker.computeMissingApiGetterSetter((TN4Classifier) type, cmoft.concreteAccessorTuples);
List<AccessorTuple> computedMissingApiFields = apiTracker.computeMissingApiFields((TN4Classifier) type);
// In case of field vs. getter the implementation should be free to choose the form.
// So filter out all missing set/get pairs which are backed by a field (either concrete or inherited)
List<AccessorTuple> filteredMissingApiGetterSetter = filterOutTuplesImplementedByField(computedMissingApiGetterSetter, cmoft.ownedAndMixedInConcreteMembers, cmoft.concreteInheritedMembers);
// Some logic applies to missing fields which are backed by a getter/setter. The situation here is a
// little bit more complex as the set/get must be processed as a pair and one could be missing or they stem
// from different (super-)types.
// *Beware* not side-effect free since we have to mix in virtual getter/setter into an existing but
// incomplete accessor-pairs
List<AccessorTuple> filteredMissingApiFields0 = filterMissingApiFieldsAndEnrichExistingTuples(computedMissingApiFields, cmoft.concreteAccessorTuples);
List<AccessorTuple> filteredMissingApiFields = filterMissingApiFieldsImplementedBySuperGetSet(filteredMissingApiFields0, cmoft.concreteInheritedMembers);
missingApiAccessorTuples.addAll(filteredMissingApiGetterSetter);
missingApiAccessorTuples.addAll(filteredMissingApiFields);
}
MemberList<TField> fieldsOverridingAccessors = getFieldsOverridingAccessor(cmoft.ownedAndMixedInConcreteMembers, cmoft.concreteInheritedMembers);
// compute the list of mixed in fields, which do not override any Accessor (handled separately)
MemberList<TField> fieldsPurelyMixedInNotOverridingAccessor = new MemberList<>();
fieldsPurelyMixedInNotOverridingAccessor.addAll(cmoft.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 MissingApiMembersForTranspiler(missingApiMethods, missingApiAccessorTuples);
}
use of org.eclipse.n4js.ts.types.TClassifier in project n4js by eclipse.
the class PrimitiveTypeImpl method setAutoboxedType.
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setAutoboxedType(TClassifier newAutoboxedType) {
TClassifier oldAutoboxedType = autoboxedType;
autoboxedType = newAutoboxedType;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, TypesPackage.PRIMITIVE_TYPE__AUTOBOXED_TYPE, oldAutoboxedType, autoboxedType));
}
Aggregations