Commit ffbd9801 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ improved handling of nested types and tails, #30, #21, #8

parent b3267fd0
Loading
Loading
Loading
Loading
+152 −20
Original line number Diff line number Diff line
@@ -68,6 +68,12 @@ import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.scoping.IScope

import static org.eclipse.xtext.scoping.Scopes.*
import de.ugoe.cs.swe.tTCN3.StructFieldDef
import de.ugoe.cs.swe.tTCN3.NestedUnionDef
import de.ugoe.cs.swe.tTCN3.NestedRecordDef
import de.ugoe.cs.swe.tTCN3.NestedSetDef
import de.ugoe.cs.swe.tTCN3.UnionFieldDef
import de.ugoe.cs.swe.tTCN3.FieldReference

class TTCN3ScopeHelper {

@@ -489,11 +495,22 @@ class TTCN3ScopeHelper {
		}
	}
	
	def static Iterable<FieldReference> getFields(EObject type) {
		var Iterable<FieldReference> fields = newArrayList
		if (type instanceof ReferencedType) {
			//TODO: test if this is always the case
			fields = type.scopeReferencedFields.map[it as FieldReference]
		} else if (type instanceof NestedTypeDef) {
			fields = type.nestedTypeFieldElements
		}
		return fields
	}
	
	def static Iterable<EObject> scopeReferencedFields(ReferencedType type) {
		val List<EObject> list = newArrayList
		val ReferencedType originalType = findOriginalType(type)

		if (originalType == null)
		if (originalType === null)
			return list;

		if (originalType instanceof RecordDefNamed) {
@@ -515,29 +532,48 @@ class TTCN3ScopeHelper {
	}	
	
	def static Iterable<EObject> scopeReferencedFields(TypeReference type) {
		scopeReferencedFields(getReferencedType(type))
		scopeReferencedFields(getReferencedTypeWithTail(type))
	}

	def static Iterable<FieldReference> nestedTypeFieldElements(NestedTypeDef type) {
		val List<FieldReference> list = newArrayList
		if (type instanceof NestedUnionDef) {
			list.addAll(type.defs)
		} else if (type instanceof NestedRecordDef) {
			list.addAll(type.defs)
		} else if (type instanceof NestedSetDef) {
			list.addAll(type.defs)
		}
		return list
	}


	def static Iterable<RefValueElement> templateFieldScope(TypeReference ref) {
		val ArrayList<RefValueElement> list = newArrayList

		if (ref == null)
		if (ref === null)
			return list

		val type = findOriginalType(getReferencedType(ref))
		val type = getReferencedOrNestedTypeWithTail(ref)
		
		if (type != null && typeof(RecordDefNamed).isAssignableFrom(type.class)) {
		//TODO: replace with getFields?
		if (type instanceof NestedTypeDef) {
			list.addAll(type.nestedTypeFieldElements)
		} else if (type instanceof ReferencedType) {
			//TODO: does it even need to be original?
			var originalType = findOriginalType(type)
			if (typeof(RecordDefNamed).isAssignableFrom(originalType.class)) {
				list.addAll((type as RecordDefNamed).body.defs)
			}
		if (type != null && typeof(UnionDefNamed).isAssignableFrom(type.class)) {
			if (typeof(UnionDefNamed).isAssignableFrom(originalType.class)) {
				list.addAll((type as UnionDefNamed).body.defs)
			}
		if (type != null && typeof(SetDefNamed).isAssignableFrom(type.class)) {
			if (typeof(SetDefNamed).isAssignableFrom(originalType.class)) {
				list.addAll((type as SetDefNamed).body.defs)
			}
		if (type != null && typeof(SignatureDef).isAssignableFrom(type.class)) {
			if (typeof(SignatureDef).isAssignableFrom(originalType.class)) {
				list.addAll((type as SignatureDef).paramList.params)
			}
		}
		list
	}

@@ -604,18 +640,114 @@ class TTCN3ScopeHelper {
		}
	}

	def static EObject getReferencedOrNestedTypeWithTail(TypeReference reference) {
		if (reference === null)
			return null;
		var EObject type = reference.head
		var TypeReferenceTail tail = reference.tail

		while (tail !== null) {
			val t = tail.type
			if (t instanceof ReferencedType) {
				type = t
				tail = tail.tail
			} else if (t instanceof StructFieldDef) {
				if (t.type !== null) {
					if (t.type.ref !==null) {
						type = getReferencedType(t.type.ref)
					}
				} else if (t.nestedType !== null) {
					type = t.nestedType
				}
				tail = tail.tail
			} else if (t instanceof UnionFieldDef) {
				if (t.type !== null) {
					if (t.type.ref !==null) {
						type = getReferencedType(t.type.ref)
					}
				} else if (t.nestedType !== null) {
					type = t.nestedType
				}
				tail = tail.tail
			} else {
				tail = null
			}
		}
		return type;
	}

	//TODO: replace with getReferencedOrNestedTypeWithTail?
	def static ReferencedType getReferencedTypeWithTail(TypeReference reference) {
		if (reference === null)
			return null;

		var TypeReferenceTail tail = reference.tail
		var ReferencedType type = reference.head

		if (type === null) {
			return type;
		}

		while (tail !== null) {
			val t = tail.type
			if (t instanceof ReferencedType) {
				type = t
				tail = tail.tail
			} else if (t instanceof StructFieldDef) {
				//TODO: handle nested types or already upstream...
				if (t.type !== null) {
					if (t.type.ref !==null) {
						type = getReferencedType(t.type.ref)
						//TODO: multiple nesting?
					}
				}
				tail = tail.tail
			} else {
				tail = null
			}
		}
		return type;
	}

	//TODO: replace with getReferencedOrNestedTypeWithTail?
	def static NestedTypeDef getNestedTypeWithTail(TypeReference reference) {
		var NestedTypeDef type = null
		if (reference === null)
			return type;

		var TypeReferenceTail tail = reference.tail

		while (tail !== null) {
			val t = tail.type
			if (t instanceof ReferencedType) {
				tail = tail.tail
			} else if (t instanceof StructFieldDef) {
				//TODO: handle nested types or already upstream...
				if (t.nestedType !== null) {
					type = t.nestedType
				}
				tail = tail.tail
			} else {
				tail = null
			}
		}

		return type;
	}

	//TODO: replace with getReferencedOrNestedTypeWithTail?
	def static ReferencedType getReferencedType(TypeReference reference) {
		if (reference == null)
		if (reference === null)
			return null;

		var TypeReferenceTail tail = reference.tail
		var ReferencedType type = reference.head

		if (type == null) {
		if (type === null) {
			return type;
		}

		while (tail != null) {
		while (tail !== null) {
			val t = tail.type
			if (t instanceof ReferencedType) {
				type = t
+54 −4
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ import org.eclipse.xtext.EcoreUtil2
import de.ugoe.cs.swe.tTCN3.SingleValueSpec
import de.ugoe.cs.swe.tTCN3.PortReceiveOp
import de.ugoe.cs.swe.tTCN3.Value
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
import de.ugoe.cs.swe.tTCN3.Assignment
import de.ugoe.cs.swe.tTCN3.TemplateInstance
import de.ugoe.cs.swe.tTCN3.TemplateRefWithParList
@@ -98,6 +97,8 @@ class TTCN3ScopeProvider extends AbstractDeclarativeScopeProvider {
	final static Logger LOG = Logger.getLogger(TTCN3LocalScopeProvider);
	static HashMap<EObject, HashMap<EObject, List<EObject>>> cache = newHashMap
	static HashMap<EObject, HashMap<EObject, List<EObject>>> importedCache = newHashMap
	public static HashMap<EObject, Integer> tailTrail = newHashMap
	public static HashMap<EObject, Integer> tailTrailCurrent = newHashMap

	def IScope scope_FieldSpec_ref(FieldSpec spec, EReference ref) {
		spec.scopeFieldExpressionList
@@ -597,6 +598,8 @@ class TTCN3ScopeProvider extends AbstractDeclarativeScopeProvider {
		if ((eContainer as TypeReference).head instanceof ImportAlias) {
			scopeFor(((eContainer as TypeReference).head.eContainer as SpecTypeElement).directTypeElements)
		} else {
			tailTrail.putIfAbsent(it, 0);
			tailTrailCurrent.putIfAbsent(it, 0);
			scopeFor((eContainer as SpecTypeElement).directTypeElements)
		}
	}
@@ -732,12 +735,48 @@ class TTCN3ScopeProvider extends AbstractDeclarativeScopeProvider {
		}
	}

	//TODO: is this really used?
	private def dispatch Iterable<EObject> directTypeElements(FieldReference it) {
		directFieldTypeElements
	}

	private def dispatch Iterable<EObject> directTypeElements(SpecTypeElement it) {
		//TODO: quite a hack.. figure out something better
		if (it instanceof TypeReference && it.tail !== null) {
			var t = (it as TypeReference)
			var level = tailTrail.get(t.tail)
			var list = newLinkedList
			if (level === 0) {
				tailTrailCurrent.put(t.tail, level+1)
				var e = t.head.directTypeElements
				list.addAll(e)
				tailTrail.put(t.tail, level+1)
			} else {
				var nextTail = t.tail
				var l = 1
				while (nextTail !== null && l <= level) {
					if (l == level && tailTrailCurrent.get(t.tail) <= level) {
						tailTrailCurrent.put(t.tail, level+1)
						var e = nextTail.directTypeElements
						list.addAll(e)
						tailTrail.put(t.tail, level+1)
					}
					l++
					nextTail = nextTail.tail
				}
			}
			//DONE?: This is a bit of a mess, as always the first tail is provided, 
			//		at first the type is not known but then it is resolved, 
			//		and only after the next one is resolved -> need to keep track
			//		As this can overshoot expanding to all fields of all types it needs to be restricted -> restricted  
			list			
		} else {
			switch it {
				TypeReference: head.directTypeElements
				TypeReferenceTail: type.directTypeElements
			}
		}
	}

	private def Iterable<EObject> directModuleTypes(TTCN3Module it) {
		val List<EObject> list = newArrayList
@@ -762,10 +801,21 @@ class TTCN3ScopeProvider extends AbstractDeclarativeScopeProvider {
		return res
	}

	private def Iterable<EObject> nestedFieldTypeElements(StructFieldDef field) {
		val List<EObject> list = newArrayList
		if (field.nestedType !== null) {
			list.addAll(field.nestedType.nestedTypeFieldElements)
		}
		return list
	}

	//TODO: replace with get fields?
	private def Iterable<EObject> directFieldTypeElements(FieldReference field) {
		if (field instanceof StructFieldDef) {
			if (field.type !== null) {
				field.type.ref.scopeReferencedFields
			} else if (field.nestedType !== null) {
				field.nestedFieldTypeElements
			}
		} else if (field instanceof FormalValuePar) {
			if (field.type !== null) {