/*******************************************************************************
* Copyright (c) 2012 BMW Car IT 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.jnario.spec.scoping;
import static com.google.common.collect.Iterables.filter;
import static org.eclipse.xtext.EcoreUtil2.getContainerOfType;
import static org.eclipse.xtext.scoping.Scopes.scopeFor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtend.core.jvmmodel.IXtendJvmAssociations;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.util.TypeReferences;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.jnario.spec.naming.OperationNameProvider;
import org.jnario.spec.spec.ExampleGroup;
import org.jnario.spec.spec.SpecPackage;
import com.google.common.base.Function;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* @author Sebastian Benz - Initial contribution and API
*/
@SuppressWarnings("restriction")
@Singleton
public class SpecScopeProvider extends AbstractDeclarativeScopeProvider {
@Inject
private IXtendJvmAssociations xtendjvmAssociations;
@Inject
private TypeReferences typeReferences;
@Inject
private OperationNameProvider operationNameProvider;
@Override
public IScope getScope(EObject context, EReference reference) {
if(reference == SpecPackage.Literals.EXAMPLE_GROUP__TARGET_OPERATION){
return targetOperation(context, reference);
}
return super.getScope(context, reference);
}
private IScope targetOperation(EObject subject, EReference reference) {
ExampleGroup context = getContainerOfType(subject.eContainer(), ExampleGroup.class);
if(context == null){
return IScope.NULLSCOPE;
}
JvmTypeReference targetTypeReference = context.getTargetType();
if(targetTypeReference == null){
return IScope.NULLSCOPE;
}
JvmType targetType = targetTypeReference.getType();
if(targetType == null || targetType.eIsProxy()){
return IScope.NULLSCOPE;
}
if (!(targetType instanceof JvmGenericType)) {
return IScope.NULLSCOPE;
}
Iterable<JvmOperation> operations = filter(((JvmGenericType) targetType).getMembers(), JvmOperation.class);
IScope simpleNames = scopeFor(operations, simpleNameProvider(), IScope.NULLSCOPE);
return scopeFor(operations, operationNameProvider, simpleNames);
}
private Function<JvmOperation, QualifiedName> simpleNameProvider() {
return new Function<JvmOperation, QualifiedName>(){
public QualifiedName apply(JvmOperation input) {
return QualifiedName.create(input.getSimpleName());
}
};
}
}