Search in sources :

Example 6 with AccessorTuple

use of org.eclipse.n4js.ts.types.util.AccessorTuple 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();
}
Also used : TSetter(org.eclipse.n4js.ts.types.TSetter) ProjectComparisonEntry(org.eclipse.n4js.compare.ProjectComparisonEntry) Inject(com.google.inject.Inject) TClass(org.eclipse.n4js.ts.types.TClass) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TSetter(org.eclipse.n4js.ts.types.TSetter) Logger(org.apache.log4j.Logger) TGetterImpl(org.eclipse.n4js.ts.types.impl.TGetterImpl) TMethodImpl(org.eclipse.n4js.ts.types.impl.TMethodImpl) Type(org.eclipse.n4js.ts.types.Type) MemberList(org.eclipse.n4js.ts.types.util.MemberList) N4InterfaceDeclaration(org.eclipse.n4js.n4JS.N4InterfaceDeclaration) TFieldImpl(org.eclipse.n4js.ts.types.impl.TFieldImpl) LinkedHashMultimap(com.google.common.collect.LinkedHashMultimap) Collections.emptyList(java.util.Collections.emptyList) Predicate(java.util.function.Predicate) TField(org.eclipse.n4js.ts.types.TField) EObject(org.eclipse.emf.ecore.EObject) PROVIDES_DEFAULT_IMPLEMENTATION(org.eclipse.n4js.AnnotationDefinition.PROVIDES_DEFAULT_IMPLEMENTATION) PROVIDES_INITIALZER(org.eclipse.n4js.AnnotationDefinition.PROVIDES_INITIALZER) TMethod(org.eclipse.n4js.ts.types.TMethod) Collectors(java.util.stream.Collectors) TGetter(org.eclipse.n4js.ts.types.TGetter) List(java.util.List) Stream(java.util.stream.Stream) TClassifier(org.eclipse.n4js.ts.types.TClassifier) Resource(org.eclipse.emf.ecore.resource.Resource) Optional(java.util.Optional) Pair(org.eclipse.xtext.xbase.lib.Pair) TypesFactory(org.eclipse.n4js.ts.types.TypesFactory) Singleton(com.google.inject.Singleton) HashMap(java.util.HashMap) TypeUtils(org.eclipse.n4js.ts.utils.TypeUtils) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) Function(java.util.function.Function) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TModule(org.eclipse.n4js.ts.types.TModule) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) TInterface(org.eclipse.n4js.ts.types.TInterface) ProjectCompareHelper(org.eclipse.n4js.compare.ProjectCompareHelper) EcoreUtil2(org.eclipse.xtext.EcoreUtil2) TAnnotableElement(org.eclipse.n4js.ts.types.TAnnotableElement) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) LinkedHashSet(java.util.LinkedHashSet) Iterator(java.util.Iterator) TMember(org.eclipse.n4js.ts.types.TMember) Script(org.eclipse.n4js.n4JS.Script) Consumer(java.util.function.Consumer) TypesPackage(org.eclipse.n4js.ts.types.TypesPackage) AdapterImpl(org.eclipse.emf.common.notify.impl.AdapterImpl) TSetterImpl(org.eclipse.n4js.ts.types.impl.TSetterImpl) Collections(java.util.Collections) HashMap(java.util.HashMap) TGetter(org.eclipse.n4js.ts.types.TGetter) ArrayList(java.util.ArrayList) Consumer(java.util.function.Consumer) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) TModule(org.eclipse.n4js.ts.types.TModule) ProjectComparisonEntry(org.eclipse.n4js.compare.ProjectComparisonEntry) Pair(org.eclipse.xtext.xbase.lib.Pair) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) TMember(org.eclipse.n4js.ts.types.TMember)

Example 7 with AccessorTuple

use of org.eclipse.n4js.ts.types.util.AccessorTuple 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);
}
Also used : VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) TField(org.eclipse.n4js.ts.types.TField) TMember(org.eclipse.n4js.ts.types.TMember) Script(org.eclipse.n4js.n4JS.Script) TClass(org.eclipse.n4js.ts.types.TClass) TMethod(org.eclipse.n4js.ts.types.TMethod) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) TSetter(org.eclipse.n4js.ts.types.TSetter) TGetter(org.eclipse.n4js.ts.types.TGetter) List(java.util.List) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) ContainerTypesHelper(org.eclipse.n4js.utils.ContainerTypesHelper) Stream(java.util.stream.Stream) TClassifier(org.eclipse.n4js.ts.types.TClassifier) TInterface(org.eclipse.n4js.ts.types.TInterface) MemberList(org.eclipse.n4js.ts.types.util.MemberList) Optional(java.util.Optional) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) TMethod(org.eclipse.n4js.ts.types.TMethod) TField(org.eclipse.n4js.ts.types.TField) MemberList(org.eclipse.n4js.ts.types.util.MemberList) TInterface(org.eclipse.n4js.ts.types.TInterface) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) MemberList(org.eclipse.n4js.ts.types.util.MemberList) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) TClass(org.eclipse.n4js.ts.types.TClass)

Example 8 with AccessorTuple

use of org.eclipse.n4js.ts.types.util.AccessorTuple in project n4js by eclipse.

the class ScriptApiTracker method computeMissingApiFields.

/**
 * Computes the list of virtual AccessorTuples for missing static fields on Interfaces
 *
 * @return List of {@link VirtualApiTField}
 */
private List<AccessorTuple> computeMissingApiFields(TInterface declaration) {
    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) {
            ArrayList<AccessorTuple> collectedMissingFields = new ArrayList<>();
            Predicate<ProjectComparisonEntry> filter = (pce -> pce.getElementAPI() instanceof TField);
            filter = filter.and(pce -> pce.getElementImpl()[0] == null).and(pce -> PROVIDES_INITIALZER.hasAnnotation((TField) pce.getElementAPI()));
            Function<TInterface, Consumer<? super ProjectComparisonEntry>> actionProvider = pivot -> pce -> {
                TField apiField = ((TField) pce.getElementAPI());
                VirtualApiMissingFieldAccessorTuple ret = createVirtFieldAccessorTuple(apiField);
                collectedMissingFields.add(ret);
            };
            if (!checkInterfaceImplementsInterface(declaration, typeCompare.getElementAPI())) {
                return emptyList();
            }
            // Call the supertype iterations scaffolding:
            interfaceApiSupertypeWalker(filter, actionProvider, projectComparisonAdapter, (TInterface) typeCompare.getElementAPI(), TInterface.class);
            return collectedMissingFields;
        }
    }
    return emptyList();
}
Also used : ProjectComparisonEntry(org.eclipse.n4js.compare.ProjectComparisonEntry) Inject(com.google.inject.Inject) TClass(org.eclipse.n4js.ts.types.TClass) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TSetter(org.eclipse.n4js.ts.types.TSetter) Logger(org.apache.log4j.Logger) TGetterImpl(org.eclipse.n4js.ts.types.impl.TGetterImpl) TMethodImpl(org.eclipse.n4js.ts.types.impl.TMethodImpl) Type(org.eclipse.n4js.ts.types.Type) MemberList(org.eclipse.n4js.ts.types.util.MemberList) N4InterfaceDeclaration(org.eclipse.n4js.n4JS.N4InterfaceDeclaration) TFieldImpl(org.eclipse.n4js.ts.types.impl.TFieldImpl) LinkedHashMultimap(com.google.common.collect.LinkedHashMultimap) Collections.emptyList(java.util.Collections.emptyList) Predicate(java.util.function.Predicate) TField(org.eclipse.n4js.ts.types.TField) EObject(org.eclipse.emf.ecore.EObject) PROVIDES_DEFAULT_IMPLEMENTATION(org.eclipse.n4js.AnnotationDefinition.PROVIDES_DEFAULT_IMPLEMENTATION) PROVIDES_INITIALZER(org.eclipse.n4js.AnnotationDefinition.PROVIDES_INITIALZER) TMethod(org.eclipse.n4js.ts.types.TMethod) Collectors(java.util.stream.Collectors) TGetter(org.eclipse.n4js.ts.types.TGetter) List(java.util.List) Stream(java.util.stream.Stream) TClassifier(org.eclipse.n4js.ts.types.TClassifier) Resource(org.eclipse.emf.ecore.resource.Resource) Optional(java.util.Optional) Pair(org.eclipse.xtext.xbase.lib.Pair) TypesFactory(org.eclipse.n4js.ts.types.TypesFactory) Singleton(com.google.inject.Singleton) HashMap(java.util.HashMap) TypeUtils(org.eclipse.n4js.ts.utils.TypeUtils) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) Function(java.util.function.Function) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TModule(org.eclipse.n4js.ts.types.TModule) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) TInterface(org.eclipse.n4js.ts.types.TInterface) ProjectCompareHelper(org.eclipse.n4js.compare.ProjectCompareHelper) EcoreUtil2(org.eclipse.xtext.EcoreUtil2) TAnnotableElement(org.eclipse.n4js.ts.types.TAnnotableElement) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) LinkedHashSet(java.util.LinkedHashSet) Iterator(java.util.Iterator) TMember(org.eclipse.n4js.ts.types.TMember) Script(org.eclipse.n4js.n4JS.Script) Consumer(java.util.function.Consumer) TypesPackage(org.eclipse.n4js.ts.types.TypesPackage) AdapterImpl(org.eclipse.emf.common.notify.impl.AdapterImpl) TSetterImpl(org.eclipse.n4js.ts.types.impl.TSetterImpl) Collections(java.util.Collections) TField(org.eclipse.n4js.ts.types.TField) TInterface(org.eclipse.n4js.ts.types.TInterface) ArrayList(java.util.ArrayList) Consumer(java.util.function.Consumer) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) TModule(org.eclipse.n4js.ts.types.TModule) ProjectComparisonEntry(org.eclipse.n4js.compare.ProjectComparisonEntry)

Aggregations

TGetter (org.eclipse.n4js.ts.types.TGetter)8 TSetter (org.eclipse.n4js.ts.types.TSetter)8 AccessorTuple (org.eclipse.n4js.ts.types.util.AccessorTuple)8 TField (org.eclipse.n4js.ts.types.TField)7 ArrayList (java.util.ArrayList)6 TInterface (org.eclipse.n4js.ts.types.TInterface)6 TMember (org.eclipse.n4js.ts.types.TMember)6 HashMap (java.util.HashMap)5 HashSet (java.util.HashSet)5 List (java.util.List)5 Collectors (java.util.stream.Collectors)5 Script (org.eclipse.n4js.n4JS.Script)5 TClass (org.eclipse.n4js.ts.types.TClass)5 TClassifier (org.eclipse.n4js.ts.types.TClassifier)5 MemberList (org.eclipse.n4js.ts.types.util.MemberList)5 MemberCollector (org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector)5 Collections.emptyList (java.util.Collections.emptyList)4 Optional (java.util.Optional)4 Stream (java.util.stream.Stream)4 LinkedHashMultimap (com.google.common.collect.LinkedHashMultimap)3