/**
* generated by Xtext
*/
package org.example.smalljava.scoping;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.example.smalljava.lib.SmallJavaLib;
import org.example.smalljava.smallJava.SJBlock;
import org.example.smalljava.smallJava.SJClass;
import org.example.smalljava.smallJava.SJExpression;
import org.example.smalljava.smallJava.SJField;
import org.example.smalljava.smallJava.SJMember;
import org.example.smalljava.smallJava.SJMemberSelection;
import org.example.smalljava.smallJava.SJMethod;
import org.example.smalljava.smallJava.SJParameter;
import org.example.smalljava.smallJava.SJStatement;
import org.example.smalljava.smallJava.SJVariableDeclaration;
import org.example.smalljava.typing.SmallJavaTypeProvider;
import org.example.smalljava.util.SmallJavaModelUtil;
/**
* This class contains custom scoping description.
*
* see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping
* on how and when to use it
*/
@SuppressWarnings("all")
public class SmallJavaScopeProvider extends AbstractDeclarativeScopeProvider {
@Inject
@Extension
private SmallJavaTypeProvider _smallJavaTypeProvider;
@Inject
@Extension
private SmallJavaLib _smallJavaLib;
public IScope scope_SJMember(final SJMemberSelection sel, final EReference r) {
IScope _xblockexpression = null;
{
IScope parentScope = IScope.NULLSCOPE;
SJExpression _receiver = sel.getReceiver();
final SJClass type = this._smallJavaTypeProvider.typeFor(_receiver);
boolean _or = false;
boolean _equals = Objects.equal(type, null);
if (_equals) {
_or = true;
} else {
boolean _isPrimitive = this._smallJavaTypeProvider.isPrimitive(type);
_or = _isPrimitive;
}
if (_or) {
return parentScope;
}
ArrayList<SJClass> _classHierarchyWithObject = this._smallJavaLib.getClassHierarchyWithObject(type);
List<SJClass> _reverseView = ListExtensions.<SJClass>reverseView(_classHierarchyWithObject);
for (final SJClass c : _reverseView) {
Iterable<SJMember> _selectMembers = this.selectMembers(c, sel);
IScope _scopeFor = Scopes.scopeFor(_selectMembers, parentScope);
parentScope = _scopeFor;
}
Iterable<SJMember> _selectMembers_1 = this.selectMembers(type, sel);
_xblockexpression = Scopes.scopeFor(_selectMembers_1, parentScope);
}
return _xblockexpression;
}
public Iterable<SJMember> selectMembers(final SJClass type, final SJMemberSelection sel) {
Iterable<SJMember> _xifexpression = null;
boolean _isMethodinvocation = sel.isMethodinvocation();
if (_isMethodinvocation) {
Iterable<SJMethod> _methods = SmallJavaModelUtil.methods(type);
Iterable<SJField> _fields = SmallJavaModelUtil.fields(type);
_xifexpression = Iterables.<SJMember>concat(_methods, _fields);
} else {
Iterable<SJField> _fields_1 = SmallJavaModelUtil.fields(type);
Iterable<SJMethod> _methods_1 = SmallJavaModelUtil.methods(type);
_xifexpression = Iterables.<SJMember>concat(_fields_1, _methods_1);
}
return _xifexpression;
}
public IScope scope_SJSymbolRef_symbol(final SJExpression context, final EReference r) {
EObject _eContainer = context.eContainer();
return this.symbolsDefinedBefore(_eContainer, context);
}
protected IScope _symbolsDefinedBefore(final EObject container, final EObject o) {
EObject _eContainer = container.eContainer();
EObject _eContainer_1 = o.eContainer();
return this.symbolsDefinedBefore(_eContainer, _eContainer_1);
}
protected IScope _symbolsDefinedBefore(final SJMethod m, final EObject o) {
EList<SJParameter> _params = m.getParams();
return Scopes.scopeFor(_params);
}
protected IScope _symbolsDefinedBefore(final SJBlock b, final EObject o) {
EList<SJStatement> _statements = b.getStatements();
Iterable<SJVariableDeclaration> _variablesDeclaredBefore = this.variablesDeclaredBefore(_statements, o);
EObject _eContainer = b.eContainer();
EObject _eContainer_1 = o.eContainer();
IScope _symbolsDefinedBefore = this.symbolsDefinedBefore(_eContainer, _eContainer_1);
return Scopes.scopeFor(_variablesDeclaredBefore, _symbolsDefinedBefore);
}
private Iterable<SJVariableDeclaration> variablesDeclaredBefore(final List<SJStatement> list, final EObject o) {
int _indexOf = list.indexOf(o);
List<SJStatement> _subList = list.subList(0, _indexOf);
return Iterables.<SJVariableDeclaration>filter(_subList, SJVariableDeclaration.class);
}
public IScope symbolsDefinedBefore(final EObject m, final EObject o) {
if (m instanceof SJMethod) {
return _symbolsDefinedBefore((SJMethod)m, o);
} else if (m instanceof SJBlock) {
return _symbolsDefinedBefore((SJBlock)m, o);
} else if (m != null) {
return _symbolsDefinedBefore(m, o);
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.<Object>asList(m, o).toString());
}
}
}