* source range of the element. This may be null.
*/
static Pair<SourceElement, SourceRange> findContainingSourceElement(SourceModel.ModuleDefn moduleDefn, SourcePosition position){
final int nTopLevelDefns = moduleDefn.getNTopLevelDefns();
SourceRange next = null;
SourceElement element = null;
for (int i = 0; i < nTopLevelDefns; i++) {
TopLevelSourceElement nthTopLevelDefn = moduleDefn.getNthTopLevelDefn(i);
// Check for matching data constructor
if (nthTopLevelDefn instanceof SourceModel.TypeConstructorDefn.AlgebraicType){
SourceModel.TypeConstructorDefn.AlgebraicType algebraicType = (AlgebraicType) nthTopLevelDefn;
for(DataConsDefn dataConsDefn : algebraicType.getDataConstructors()){
SourceRange testSourcePosition = dataConsDefn.getSourceRangeOfDefn();
if (testSourcePosition.containsPosition(position)){
if (next == null || next.contains(testSourcePosition)){
next = testSourcePosition;
element = dataConsDefn;
return new Pair<SourceElement, SourceRange>(element, element.getSourceRange());
}
}
}
}
// check for matching class method
else if (nthTopLevelDefn instanceof SourceModel.TypeClassDefn){
SourceModel.TypeClassDefn typeClassDefn = (SourceModel.TypeClassDefn) nthTopLevelDefn;
for(ClassMethodDefn classMethodDefn : typeClassDefn.getClassMethodDefns()){
SourceRange testSourcePosition = classMethodDefn.getSourceRangeOfClassDefn();
if (testSourcePosition.containsPosition(position)){
if (next == null || next.contains(testSourcePosition)){
next = testSourcePosition;
element = classMethodDefn;
return new Pair<SourceElement, SourceRange>(element, element.getSourceRange());
}
}
}
}
// check for let expressions
else if (nthTopLevelDefn instanceof SourceModel.FunctionDefn.Algebraic){
SourceModel.FunctionDefn.Algebraic algebraic = (SourceModel.FunctionDefn.Algebraic) nthTopLevelDefn;
if (algebraic.getDefiningExpr() instanceof SourceModel.Expr.Let){
SourceModel.Expr.Let let = (SourceModel.Expr.Let) algebraic.getDefiningExpr();
for(LocalDefn localDefn : let.getLocalDefinitions()){
SourceRange testSourcePosition = localDefn.getSourceRange();
if (testSourcePosition.containsPosition(position)){
if (next == null || next.contains(testSourcePosition)){
next = testSourcePosition;
element = localDefn;
if (localDefn instanceof LocalDefn.Function){
SourceModel.LocalDefn.Function localFunction = (SourceModel.LocalDefn.Function) localDefn;
// if there is a type declaration then use that to put the
// cal doc in front of
for(LocalDefn localTypeDefn : let.getLocalDefinitions()){
if (localTypeDefn instanceof SourceModel.LocalDefn.Function.TypeDeclaration){
SourceModel.LocalDefn.Function.TypeDeclaration type = (SourceModel.LocalDefn.Function.TypeDeclaration) localTypeDefn;
if (type.getName().equals(localFunction.getName())){
element = type;
}
}
}
}
if (localDefn instanceof LocalDefn.Function.Definition){
LocalDefn.Function.Definition def = (Definition) localDefn;
Pair<SourceElement, SourceRange> innerMatch = findInnermostDef(def, position);
if (innerMatch != null){
element = innerMatch.fst();
next = innerMatch.snd();
}
}
}
}
}
if (element != null){
break;
}
}
}
// check the current element
SourceRange testSourcePosition = nthTopLevelDefn.getSourceRangeOfDefn();
if (testSourcePosition.containsPosition(position)){
if (next == null || next.contains(testSourcePosition)){
next = testSourcePosition;
element = nthTopLevelDefn;
}
}
}
if (element != null){
// Find type declaration if any
if (element instanceof SourceModel.FunctionDefn){
SourceModel.FunctionDefn functionDefn = (FunctionDefn) element;
String name = functionDefn.getName();
for (int i = 0; i < nTopLevelDefns; i++) {
TopLevelSourceElement nthTopLevelDefn = moduleDefn.getNthTopLevelDefn(i);
if (nthTopLevelDefn instanceof FunctionTypeDeclaration){
FunctionTypeDeclaration type = (FunctionTypeDeclaration) nthTopLevelDefn;
if (type.getFunctionName().equals(name)){
element = type;
break;
}
}
}
}
return new Pair<SourceElement, SourceRange>(element, element.getSourceRange());
}
else{
if (moduleDefn.getSourceRange().containsPosition(position)){
return new Pair<SourceElement, SourceRange>(moduleDefn, moduleDefn.getSourceRange());
}