/*******************************************************************************
* Copyright (c) 2010-2012, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
* 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
*
* Contributors:
* Zoltan Ujhelyi - initial API and implementation
*******************************************************************************/
package org.eclipse.incquery.patternlanguage.scoping;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.incquery.patternlanguage.patternLanguage.Pattern;
import org.eclipse.incquery.patternlanguage.patternLanguage.PatternBody;
import org.eclipse.incquery.patternlanguage.patternLanguage.PatternCall;
import org.eclipse.incquery.patternlanguage.patternLanguage.Variable;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.FilteringScope;
import org.eclipse.xtext.scoping.impl.SimpleScope;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
* <p>
* An extended abstract declarative scope provider to facilitate the reusing of abstract declarative scope providers
* together with XBase scope provider.
* </p>
* <p>
* See <a href= "http://www.eclipse.org/forums/index.php/mv/msg/219841/699521/#msg_699521"
* >http://www.eclipse.org/forums/index.php/mv/msg/219841/699521/#msg_699521</a> for details.
* </p>
*
* @author Zoltan Ujhelyi
*
*/
public class PatternLanguageDeclarativeScopeProvider extends MyAbstractDeclarativeScopeProvider {
private static final class PrivateDescFilter implements Predicate<IEObjectDescription> {
@Override
public boolean apply(IEObjectDescription input) {
// filter not local, private patterns (private patterns in other
// resources)
// this information stored in the userdata of the
// EObjectDescription
// EObjectDescription only created for not local eObjects, so
// check for resource equality is unnecessary.
if ("true".equals(input.getUserData("private"))) {
return false;
}
return true;
}
}
private static final class UndefinedVariable implements Predicate<Variable> {
@Override
public boolean apply(Variable input) {
return input.getName() != null && !input.getName().isEmpty();
}
}
private static final class CreateObjectDescFunction implements Function<Variable, IEObjectDescription> {
@Override
public IEObjectDescription apply(Variable from) {
return EObjectDescription.create(from.getName(), from);
}
}
/**
* Custom scoping for patternRef in {@link PatternCall}. Currently returns all Pattern that is visible from the
* current context.
*
* @param ctx
* @param ref
* @return
*/
public IScope scope_PatternCall_patternRef(PatternCall ctx, EReference ref) {
IScope scope = delegateGetScope(ctx, ref);
return new FilteringScope(scope, new PrivateDescFilter());
}
public IScope scope_VariableReference_variable(EObject ctx, EReference ref) {
EObject it = ctx;
PatternBody body = null;
while (it != null && !(it instanceof Pattern)) {
if (it instanceof PatternBody) {
body = (PatternBody) it;
}
it = it.eContainer();
}
CreateObjectDescFunction createObjectDescFunction = new CreateObjectDescFunction();
EList<Variable> variables;
if (body != null) {
variables = body.getVariables();
} else if (it != null) {
Pattern pattern = (Pattern) it; // If it is not null, this works
variables = pattern.getParameters();
} else {
return IScope.NULLSCOPE;
}
UndefinedVariable variableFilter = new UndefinedVariable();
IScope localScope = new SimpleScope(IScope.NULLSCOPE, Iterables.transform(
Iterables.filter(variables, variableFilter), createObjectDescFunction));
return localScope;
}
}