use of org.eclipse.n4js.ts.types.TGetter in project n4js by eclipse.
the class ScriptApiTracker method _computeMissingApiGetterSetter.
/**
* Internal algorithm.
*/
private List<AccessorTuple> _computeMissingApiGetterSetter(TN4Classifier declaration, List<AccessorTuple> concreteAccessorTuples, Predicate<ProjectComparisonEntry> filterPredicate, boolean recursive) {
Optional<ProjectComparisonAdapter> optAdapt = firstProjectComparisonAdapter(declaration.eResource());
if (optAdapt.isPresent()) {
ProjectComparisonAdapter projectComparisonAdapter = optAdapt.get();
ProjectComparisonEntry compareEntry = projectComparisonAdapter.getEntryFor(EcoreUtil2.getContainerOfType(declaration, TModule.class));
ProjectComparisonEntry typeCompare = compareEntry.getChildForElementImpl(declaration);
if (typeCompare == null) {
return Collections.emptyList();
}
Predicate<ProjectComparisonEntry> filter = (pce -> (pce.getElementAPI() instanceof TGetter) || (pce.getElementAPI() instanceof TSetter));
filter = filter.and(pce -> pce.getElementImpl()[0] == null).and(filterPredicate);
ArrayList<ProjectComparisonEntry> collectedPCEofGetterOrSetter = new ArrayList<>();
Function<TN4Classifier, Consumer<? super ProjectComparisonEntry>> actionProvider = pivot -> pce -> {
// Get or Set ??
collectedPCEofGetterOrSetter.add(pce);
};
// recursive Extension will generate a stream of compareEntries.
if (recursive)
interfaceApiSupertypeWalker(filter, actionProvider, projectComparisonAdapter, (TN4Classifier) typeCompare.getElementAPI(), TN4Classifier.class);
// ----
/*-
Cases of the Implementation: A getter or setter can
- be given as AST (x)
- be missing (m)
- were not required by API (/)
So we have 3*3=9 cases:
get set
(x) (x) --> all fine, pair will be transpiled
(x) (m) --> code for getter will be transpiled, need to inject virtual setter code into existing tuple.
(x) (/) --> all fine, getter will be transpiled
(m) (x) --> code for setter will be transpiled, need to inject virtual getter code into existing tuple.
(m) (m) --> need to create virtual accessor tuple (similar to missing field) with setter & getter
(m) (/) --> need to create virtual accessor tuple with getter only
(/) (x) --> all fine
(/) (m) --> need to create virtual accessor tuple with setter only
(/) (/) --> all fine nothing to be done.
*/
List<ProjectComparisonEntry> getSetList;
if (recursive)
getSetList = collectedPCEofGetterOrSetter;
else
getSetList = typeCompare.allChildren().filter(pce -> (pce.getElementAPI() instanceof TGetter) || (pce.getElementAPI() instanceof TSetter)).filter(filterPredicate).collect(Collectors.toList());
HashMap<Pair<String, Boolean>, GetSetGroup> hmName2getset = new HashMap<>();
for (ProjectComparisonEntry pce : getSetList) {
TMember apiAsMember = ((TMember) pce.getElementAPI());
String name = apiAsMember.getName();
boolean staticCase = apiAsMember.isStatic();
Pair<String, Boolean> key = Pair.of(name, staticCase);
GetSetGroup group = hmName2getset.get(key);
if (group == null) {
group = new GetSetGroup(name, staticCase);
hmName2getset.put(key, group);
}
if (pce.getElementAPI() instanceof TGetter) {
// case getter:
TGetter apiGetter = (TGetter) pce.getElementAPI();
if (pce.getElementImpl(0) != null) {
// case (x) for getter-
group.getterIsInAST = true;
} else {
// case (m) for getter-
group.getterIsInAST = false;
group.getter = new VirtualApiTGetter(name, apiGetter);
}
} else if (pce.getElementAPI() instanceof TSetter) {
// case setter:
TSetter apiSetter = (TSetter) pce.getElementAPI();
if (pce.getElementImpl(0) != null) {
// case (x) for setter -
group.setterIsInAST = true;
} else {
// case (m) for setter:
group.setterIsInAST = false;
group.setter = new VirtualApiTSetter(name, apiSetter);
}
}
}
// go over the list of known AccessorTupels and enhance them by adding virtual things.
for (AccessorTuple conAccTupel : concreteAccessorTuples) {
GetSetGroup getset = hmName2getset.remove(Pair.of(conAccTupel.getName(), conAccTupel.isStatic()));
if (getset != null) {
// some missings found:
if (getset.hasGetter() && !getset.getterIsInAST && // could be mixed in by interface-default-impl different
conAccTupel.getGetter() == null) // to the intended API-path c.f. GHOLD-212
{
conAccTupel.setGetter(getset.getter);
}
if (getset.hasSetter() && !getset.setterIsInAST && // could be mixed in by interface-default-impl different
conAccTupel.getSetter() == null) // to the intended API-path c.f. GHOLD-212
{
conAccTupel.setSetter(getset.setter);
}
}
}
// remaining entries in hmName2getset need to translated into VirtualApiAccessors.
List<AccessorTuple> ret = new ArrayList<>();
for (GetSetGroup getset : hmName2getset.values()) {
VirtualApiAccessorTuple vAccessTupel = new VirtualApiAccessorTuple(getset.name, getset.staticCases);
if (getset.getter != null)
vAccessTupel.setGetter(getset.getter);
if (getset.setter != null)
vAccessTupel.setSetter(getset.setter);
ret.add(vAccessTupel);
}
return ret;
}
return emptyList();
}
use of org.eclipse.n4js.ts.types.TGetter in project n4js by eclipse.
the class ComposedMemberScope method createErrorPlaceholder.
/**
* To avoid having to do all computation over and over in case no valid composed member can be built, we also create
* a member in the error case as a placeholder.
* <p>
* Note: we need to be able to store error place holders and/or successfully composed members for read- and
* write-access independently (i.e. we might have, for example, a valid composed member for read access but an error
* placeholder for write access); therefore we have to use getters/setters for error place holders.
*/
private TMember createErrorPlaceholder(String memberName) {
if (writeAccess) {
final TSetter s = TypeUtils.createTSetter(memberName, null, TypeRefsFactory.eINSTANCE.createUnknownTypeRef());
s.setComposed(true);
return s;
} else {
final TGetter g = TypesFactory.eINSTANCE.createTGetter();
g.setComposed(true);
g.setName(memberName);
g.setDeclaredTypeRef(TypeRefsFactory.eINSTANCE.createUnknownTypeRef());
return g;
}
}
use of org.eclipse.n4js.ts.types.TGetter in project n4js by eclipse.
the class GetterFactory method create.
@Override
public TGetter create(String name) {
TGetter getter = TypesFactory.eINSTANCE.createTGetter();
getter.setComposed(true);
TypeRef typeRef = getReturnTypeRefComposition();
TypeUtils.setMemberTypeRef(getter, typeRef);
getter.setName(name);
getter.setDeclaredMemberAccessModifier(getAccessability());
return getter;
}
use of org.eclipse.n4js.ts.types.TGetter in project n4js by eclipse.
the class TypingStrategyFilter method apply.
@Override
public boolean apply(IEObjectDescription description) {
if (typingStrategy == TypingStrategy.DEFAULT || typingStrategy == TypingStrategy.NOMINAL) {
return true;
}
EObject proxyOrInstance = description.getEObjectOrProxy();
if (proxyOrInstance == null || proxyOrInstance.eIsProxy()) {
return true;
}
if (!(proxyOrInstance instanceof TMember)) {
return true;
}
TMember member = (TMember) proxyOrInstance;
if (member.isStatic() || member.getMemberAccessModifier() != MemberAccessModifier.PUBLIC) {
return false;
}
if (member instanceof TMethod) {
switch(typingStrategy) {
case NOMINAL:
case DEFAULT:
return true;
case STRUCTURAL_FIELDS:
case STRUCTURAL_READ_ONLY_FIELDS:
case STRUCTURAL_WRITE_ONLY_FIELDS:
case STRUCTURAL_FIELD_INITIALIZER:
return false;
case STRUCTURAL:
// including constructors
return true;
}
}
if (member instanceof TGetter) {
switch(typingStrategy) {
case NOMINAL:
case DEFAULT:
case STRUCTURAL:
case STRUCTURAL_FIELDS:
case STRUCTURAL_READ_ONLY_FIELDS:
return true;
case STRUCTURAL_WRITE_ONLY_FIELDS:
return false;
case STRUCTURAL_FIELD_INITIALIZER:
ContainerType<?> type = member.getContainingType();
NameAndAccess naa = new NameAndAccess(member.getName(), true, false);
Map<NameAndAccess, ? extends TMember> members = type.getOwnedMembersByNameAndAccess();
boolean hasSetter = members.containsKey(naa);
return hasSetter;
}
}
if (member instanceof TSetter) {
switch(typingStrategy) {
case NOMINAL:
case DEFAULT:
case STRUCTURAL:
case STRUCTURAL_FIELDS:
case STRUCTURAL_WRITE_ONLY_FIELDS:
return true;
case STRUCTURAL_READ_ONLY_FIELDS:
case STRUCTURAL_FIELD_INITIALIZER:
return false;
}
}
if (member instanceof TField) {
TField field = (TField) member;
switch(typingStrategy) {
case NOMINAL:
case DEFAULT:
case STRUCTURAL:
case STRUCTURAL_FIELDS:
return true;
case STRUCTURAL_READ_ONLY_FIELDS:
return !isWriteAccess;
case STRUCTURAL_WRITE_ONLY_FIELDS:
return isWriteAccess;
case STRUCTURAL_FIELD_INITIALIZER:
boolean isAccessable = !isWriteAccess && (!field.isFinal() || !field.isHasExpression());
return isAccessable;
}
}
return true;
}
use of org.eclipse.n4js.ts.types.TGetter in project n4js by eclipse.
the class TypeUtils method setMemberTypeRef.
/**
* Convenience method setting the type of the given member. Sets the return type in case of getters and methods and
* the type of the single fpar in case of setters. If the setter does not have an fpar yet, it will be created.
*/
public static void setMemberTypeRef(TMember m, TypeRef typeRef) {
typeRef = TypeUtils.copyIfContained(typeRef);
if (m instanceof TField)
((TField) m).setTypeRef(typeRef);
else if (m instanceof TGetter)
((TGetter) m).setDeclaredTypeRef(typeRef);
else if (m instanceof TSetter) {
final TSetter s = (TSetter) m;
if (s.getFpar() == null)
s.setFpar(TypesFactory.eINSTANCE.createTFormalParameter());
s.getFpar().setTypeRef(typeRef);
} else if (m instanceof TMethod)
((TMethod) m).setReturnTypeRef(typeRef);
else if (m != null)
throw new IllegalArgumentException("unknown sub-class of TMember: " + m.getClass().getName());
}
Aggregations