org.eclipse.xtext.xbase.scoping.batch.ConstructorScopes.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtext.xbase.scoping.batch.ConstructorScopes.java

Source

/*******************************************************************************
 * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.xtext.xbase.scoping.batch;

import java.util.Collections;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.common.types.JvmConstructor;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmMember;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.JvmVisibility;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.xbase.XConstructorCall;
import org.eclipse.xtext.xbase.XbasePackage;
import org.eclipse.xtext.xbase.typesystem.IResolvedTypes;
import org.eclipse.xtext.xbase.typesystem.util.IVisibilityHelper;

import com.google.common.collect.Iterables;
import com.google.inject.Inject;

/**
 * Encapsulates the creation of constructor scopes.
 * 
 * @author Sebastian Zarnekow - Initial contribution and API
 */
public class ConstructorScopes {

    public static final int CONSTRUCTOR_BUCKET = 1;

    @Inject
    private IQualifiedNameConverter qualifiedNameConverter;

    @Inject
    private TypeScopes typeScopes;

    /**
     * Creates the constructor scope for {@link XConstructorCall}.
     * The scope will likely contain descriptions for {@link JvmConstructor constructors}.
     * If there is not constructor declared, it may contain {@link JvmType types}.
     * 
     * @param session the currently available visibilityHelper data
     * @param reference the reference that will hold the resolved constructor
     * @param resolvedTypes the currently known resolved types
     */
    public IScope createConstructorScope(EObject context, EReference reference, IFeatureScopeSession session,
            IResolvedTypes resolvedTypes) {
        if (!(context instanceof XConstructorCall)) {
            return IScope.NULLSCOPE;
        }
        /*
         * We use a type scope here in order to provide better feedback for users,
         * e.g. if the constructor call refers to an interface or a primitive.
         */
        final IScope delegateScope = typeScopes.createTypeScope(context,
                TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE, session, resolvedTypes);
        IScope result = new ConstructorTypeScopeWrapper(context, session, delegateScope);
        return result;
    }

    /**
     * Custom languages that allow to infer anonymous classes may want to use this helper
     * to access the constructors of those classes.
     * @param session subtypes may override and use the given session.
     */
    protected IScope createAnonymousClassConstructorScope(final JvmGenericType anonymousType, EObject context,
            final IFeatureScopeSession session) {
        // we don't care about the type scope since the type is well known here
        IVisibilityHelper protectedIsVisible = new IVisibilityHelper() {
            @Override
            public boolean isVisible(/* @NonNull */ JvmMember member) {
                return member.getVisibility() != JvmVisibility.PRIVATE;
            }
        };
        return new ConstructorTypeScopeWrapper(context, protectedIsVisible, IScope.NULLSCOPE) {
            @Override
            public Iterable<IEObjectDescription> getElements(EObject object) {
                throw new UnsupportedOperationException("TODO implement as necessary");
            }

            @Override
            public Iterable<IEObjectDescription> getElements(QualifiedName name) {
                JvmTypeReference superType = Iterables.getLast(anonymousType.getSuperTypes(), null);
                if (superType == null)
                    return Collections.emptyList();
                JvmType type = superType.getType();
                if (type == null)
                    return Collections.emptyList();
                QualifiedName typeName = qualifiedNameConverter.toQualifiedName(type.getQualifiedName('.'));
                if (typeName.getSegmentCount() > name.getSegmentCount()) {
                    typeName = typeName.skipFirst(typeName.getSegmentCount() - name.getSegmentCount());
                }
                if (!typeName.equals(name)) {
                    if (name.getSegmentCount() == 1 && name.getFirstSegment().indexOf('$') > 0) {
                        QualifiedName splitted = QualifiedName.create(Strings.split(name.getFirstSegment(), '$'));
                        typeName = qualifiedNameConverter.toQualifiedName(type.getQualifiedName('.'));
                        if (typeName.getSegmentCount() > splitted.getSegmentCount()) {
                            typeName = typeName.skipFirst(typeName.getSegmentCount() - splitted.getSegmentCount());
                        }
                        if (!typeName.equals(splitted)) {
                            return Collections.emptyList();
                        }
                    } else {
                        return Collections.emptyList();
                    }
                }
                IEObjectDescription typeDescription = EObjectDescription.create(name, anonymousType);
                return createFeatureDescriptions(Collections.singletonList(typeDescription));
            }

            @Override
            protected ConstructorDescription createConstructorDescription(IEObjectDescription typeDescription,
                    JvmConstructor constructor, boolean visible) {
                return createAnonmousClassConstructorDescription(typeDescription.getName(), constructor, visible);
            }
        };
    }

    protected ConstructorDescription createAnonmousClassConstructorDescription(QualifiedName name,
            JvmConstructor constructor, boolean visible) {
        ConstructorDescription result = new ConstructorDescription(name, constructor,
                ConstructorScopes.CONSTRUCTOR_BUCKET, visible, true);
        return result;
    }

    public boolean isConstructorCallScope(EReference reference) {
        return reference == XbasePackage.Literals.XCONSTRUCTOR_CALL__CONSTRUCTOR;
    }

}