SemanticAdaptationScopeProvider.xtend 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*******************************************************************************
  2. * Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *******************************************************************************/
  8. package be.uantwerpen.ansymo.semanticadaptation.scoping
  9. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
  10. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.AlgebraicLoopSolution
  11. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Component
  12. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Connection
  13. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
  14. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Declaration
  15. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.FMU
  16. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.For
  17. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.FunctionDeclaration
  18. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.If
  19. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InOutRules
  20. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.LValueDeclaration
  21. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutputFunction
  22. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
  23. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
  24. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptationPackage
  25. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SpecifiedPort
  26. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StateTransitionFunction
  27. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
  28. import com.google.common.base.Predicate
  29. import com.google.inject.Inject
  30. import java.util.LinkedList
  31. import java.util.List
  32. import org.eclipse.emf.common.util.BasicEList
  33. import org.eclipse.emf.common.util.EList
  34. import org.eclipse.emf.ecore.EObject
  35. import org.eclipse.emf.ecore.EReference
  36. import org.eclipse.emf.ecore.resource.Resource
  37. import org.eclipse.xtext.EcoreUtil2
  38. import org.eclipse.xtext.resource.IEObjectDescription
  39. import org.eclipse.xtext.scoping.IGlobalScopeProvider
  40. import org.eclipse.xtext.scoping.IScope
  41. import org.eclipse.xtext.scoping.Scopes
  42. import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider
  43. import org.eclipse.xtext.scoping.impl.IScopeWrapper
  44. import be.uantwerpen.ansymo.semanticadaptation.log.Log
  45. /**
  46. * This class contains custom scoping description.
  47. *
  48. * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
  49. * on how and when to use it.
  50. */
  51. class SemanticAdaptationScopeProvider extends AbstractDeclarativeScopeProvider {
  52. /* provides a global scope for all elements!
  53. * overrides all the remainder of this class
  54. */
  55. override getScope(EObject context, EReference reference) {
  56. Log.push("Getting scope for " + reference.name + " within context " + context.class)
  57. // TODO: This does not work for semantic adaptations on multiple files.
  58. // There is incomplete code for that below.
  59. if (reference.name == "port" && context instanceof SpecifiedPort){
  60. var portRef = context as SpecifiedPort
  61. if (portRef.owner !== null){
  62. val scopeFound = getFMUScope(portRef.owner)
  63. Log.pop("Scope found:" + scopeFound)
  64. return scopeFound
  65. } else {
  66. val scopeFound = getGenericScopePort(context)
  67. Log.pop("Scope found:" + scopeFound)
  68. return scopeFound
  69. }
  70. }
  71. if (reference.name == "port" && context instanceof Port){
  72. val scopeFound = getGenericScopePort(context)
  73. Log.pop("Scope found:" + scopeFound)
  74. return scopeFound
  75. }
  76. if (reference.name == "ref" && context instanceof Variable){
  77. var variable = context as Variable
  78. if(variable.owner !== null){
  79. val scopeFound = getFMUScope(variable.owner)
  80. Log.pop("Scope found:" + scopeFound)
  81. return scopeFound
  82. } else {
  83. var rootContainner = EcoreUtil2.getRootContainer(context)
  84. val scopeFound = Scopes.scopeFor(EcoreUtil2.getAllContentsOfType(rootContainner, LValueDeclaration))
  85. Log.pop("Scope found:" + scopeFound)
  86. return scopeFound
  87. }
  88. }
  89. /*
  90. println("Getting broader scope...")
  91. if (reference === SemanticAdaptationPackage.Literals.IMPORT__MODULE) {
  92. return getGlobalScope(context.eResource, reference)
  93. }
  94. val module = EcoreUtil2.getContainerOfType(context, SemanticAdaptation)
  95. var moduleScope = IScope.NULLSCOPE
  96. for (import : module.imports) {
  97. if (!import.module.eIsProxy)
  98. moduleScope = getModuleScope(context, reference, import.module, moduleScope)
  99. }
  100. moduleScope = getModuleScope(context, reference, module, moduleScope)
  101. val scopeFound = Scopes.scopeFor(context.eResource.allContents.toList, moduleScope)
  102. println("Scope found:" + scopeFound)
  103. return scopeFound
  104. */
  105. Log.println("Delegating scope discovery to super class...")
  106. val scopeFound = super.getScope(context, reference)
  107. Log.pop("Scope found:" + scopeFound)
  108. return scopeFound
  109. }
  110. def getGenericScopePort(EObject context) {
  111. Log.println("Getting all port declarations")
  112. var rootContainner = EcoreUtil2.getRootContainer(context)
  113. val scopeFound = Scopes.scopeFor(EcoreUtil2.getAllContentsOfType(rootContainner, Port))
  114. return scopeFound
  115. }
  116. def getFMUScope(FMU fmu) {
  117. Log.println("Getting scope within FMU: " + fmu.name)
  118. val scopeFound = Scopes.scopeFor(EcoreUtil2.getAllContentsOfType(fmu, Port))
  119. return scopeFound
  120. }
  121. /*
  122. override getScope(EObject context, EReference reference) {
  123. println("Getting scope for " + reference + " within context " + context)
  124. if (reference === SemanticAdaptationPackage.Literals.IMPORT__MODULE) {
  125. return getGlobalScope(context.eResource, reference)
  126. }
  127. val module = EcoreUtil2.getContainerOfType(context, SemanticAdaptation)
  128. var result = IScope.NULLSCOPE
  129. for (import : module.imports) {
  130. if (!import.module.eIsProxy)
  131. result = getModuleScope(context, reference, import.module, result)
  132. }
  133. result = getModuleScope(context, reference, module, result)
  134. //println(Scopes.scopeFor(context.eResource.allContents.toList, result))
  135. return Scopes.scopeFor(context.eResource.allContents.toList, result)
  136. }
  137. */
  138. // TODO: only correct src and tgt references
  139. def scope_Connection_src(Connection context, EReference r) {
  140. return __getImportedScope(context, r).__addScope(__getAllPorts(context))
  141. }
  142. def scope_Connection_tgt(Connection context, EReference r) {
  143. return __getImportedScope(context, r).__addScope(__getAllPorts(context))
  144. }
  145. def scope_Port_target(Port context, EReference r) {
  146. return __getImportedScope(context, r).__addScope(__getAllPorts(context))
  147. }
  148. def scope_AlgebraicLoopSolution_signals(AlgebraicLoopSolution context, EReference r) {
  149. return __getImportedScope(context, r).__addScope(__getAllPorts(context))
  150. }
  151. def scope_Variable_ref(Variable context, EReference r) {
  152. //println(context.eContainer())
  153. //var scope = __getImportedScope(context, r)
  154. var EList<EObject> elements = __getAllPorts(context)
  155. val outputfunction = EcoreUtil2.getContainerOfType(context, OutputFunction)
  156. if (outputfunction !== null) {
  157. val rule = outputfunction.eContainer as DataRule
  158. if (rule.statetransitionfunction !== null) {
  159. elements += rule.statetransitionfunction.statements
  160. }
  161. }
  162. elements += context.__getFrom(If, "ifstatements", Declaration, true).flatten
  163. elements += context.__getFrom(If, "ifstatements", FunctionDeclaration, true).flatten
  164. elements += context.__getFrom(For, "iterator", null, true).flatten
  165. elements += context.__getFromElement(StateTransitionFunction, "statements", Declaration)
  166. elements += context.__getFromElement(StateTransitionFunction, "statements", FunctionDeclaration)
  167. elements += context.__getFromElement(InOutRules, "globalvars")
  168. elements += context.__getFromElement(InOutRules, "iterationvars")
  169. elements += context.__getFromElement(Adaptation, "params")
  170. return __getImportedScope(context, r).__addScope(elements)
  171. }
  172. def scope_Adaptation_instances(Adaptation context, EReference r) {
  173. return __getImportedScope(context, r)
  174. }
  175. def scope_Adaptation_ports(Adaptation context, EReference r) {
  176. return __getImportedScope(context, r)
  177. }
  178. def scope_CompositeFMU_instances(SemanticAdaptation context, EReference r) {
  179. return __getImportedScope(context, r)
  180. }
  181. /*def scope_Step_fmu(Step context, EReference r) {
  182. return Scopes.scopeFor(EcoreUtil2.getContainerOfType(context, Adaptation).inner.instances, IScope.NULLSCOPE)
  183. }*/
  184. /*def EObject __getAncestorOfType(EObject object, Class<?> type) { // same as EcoreUtil2.getContainerOfType
  185. val parent = object.eContainer
  186. if (parent == null) {
  187. return null
  188. }
  189. if (type.isAssignableFrom(parent.class)) {
  190. return parent
  191. } else{
  192. return __getAncestorOfType(object.eContainer, type)
  193. }
  194. }*/
  195. def __addScope(IScope scope, EList elements) {
  196. return Scopes.scopeFor(elements, scope)
  197. }
  198. def __getAllPorts(EObject context) {
  199. val module = EcoreUtil2.getContainerOfType(context, SemanticAdaptation)
  200. var elementlist = new BasicEList<EObject>;
  201. for (Component element : module.elements) {
  202. if (element instanceof FMU) {
  203. elementlist += element.inports+element.outports
  204. }
  205. }
  206. return elementlist
  207. }
  208. def __getFromElement(EObject context, Class<? extends EObject> containertype, String featurename, Class<? extends EObject> featuretype) {
  209. /*val object = EcoreUtil2.getContainerOfType(context, containertype)
  210. if (object != null) {
  211. val feature = object.eClass.EAllStructuralFeatures.findFirst(f | f.name.equals(featurename))
  212. if (feature != null) {
  213. val featurevalue = object.eGet(feature)
  214. if (featurevalue instanceof EList) {
  215. if (featuretype != null) {
  216. return featurevalue.filter(v | featuretype.isInstance(v))
  217. } else {
  218. return featurevalue
  219. }
  220. } else {
  221. if (featuretype == null || featuretype.isInstance(featurevalue)) {
  222. val featurevaluelist = new BasicEList()
  223. featurevaluelist.add(featurevalue)
  224. return featurevaluelist
  225. }
  226. }
  227. } else {
  228. throw new Exception("Feature " + featurename + " not found in object of type " + containertype.name)
  229. }
  230. }
  231. return new BasicEList<EObject>()*/
  232. return context.__getFrom(containertype, featurename, featuretype, false).flatten
  233. }
  234. def __getFromElement(EObject context, Class<? extends EObject> containertype, String featurename) {
  235. return context.__getFromElement(containertype, featurename, null)
  236. }
  237. /**
  238. * Look from context to root for elements
  239. * @params:
  240. * context: element to start from
  241. * containertype: type of elements that have a feature that needs to be found
  242. * featurename: name of feature that must be a feature of containertype
  243. * featuretype: only take features of featuretype
  244. * all: if true: go through all instances of container type; if false: only the first encounter from context to root
  245. *
  246. * @returns:
  247. * all: list of lists of found elements (from context to root)
  248. * !all: list of found elements (first encounter from context to root)
  249. */
  250. def List<? extends List<? extends EObject>> __getFrom(EObject context, Class<? extends EObject> containertype, String featurename, Class<? extends EObject> featuretype, boolean all) {
  251. val List<List<EObject>> listOfElementLists = new LinkedList<List<EObject>>()
  252. for (object : EcoreUtil2.getAllContainers(context)) {
  253. if (containertype.isInstance(object)) {
  254. val List<EObject> listOfElements = new LinkedList<EObject>()
  255. val feature = object.eClass.EAllStructuralFeatures.findFirst(f | f.name.equals(featurename))
  256. if (feature !== null) {
  257. val featurevalue = object.eGet(feature)
  258. if (featurevalue instanceof EList) {
  259. if (featuretype !== null) {
  260. listOfElements.addAll(featurevalue.filter(v | featuretype.isInstance(v)).map(v | v as EObject))
  261. } else {
  262. listOfElements.addAll(featurevalue)
  263. }
  264. } else if (featurevalue instanceof EObject) {
  265. if (featuretype === null || featuretype.isInstance(featurevalue)) {
  266. listOfElements.add(featurevalue)
  267. }
  268. } else {
  269. throw new Exception("todo")
  270. }
  271. } else {
  272. throw new Exception("Feature " + featurename + " not found in object of type " + containertype.name)
  273. }
  274. listOfElementLists.add(listOfElements)
  275. if (!all) {
  276. return listOfElementLists
  277. }
  278. }
  279. }
  280. return listOfElementLists
  281. }
  282. @Inject
  283. private IGlobalScopeProvider globalScopeProvider;
  284. def protected IScope getGlobalScope(Resource context, EReference reference) {
  285. return getGlobalScope(context, reference, null);
  286. }
  287. def protected IScope getGlobalScope(Resource context, EReference reference, Predicate<IEObjectDescription> filter) {
  288. return wrap(globalScopeProvider.getScope(context, reference, filter));
  289. }
  290. private IScopeWrapper scopeWrapper;
  291. def public void setWrapper(IScopeWrapper wrapper) {
  292. this.scopeWrapper = wrapper;
  293. }
  294. def protected IScope wrap(IScope scope) {
  295. if (scopeWrapper!==null){
  296. return scopeWrapper.wrap(scope)
  297. } else {
  298. return scope
  299. }
  300. }
  301. def __getImportedScope(EObject context, EReference reference) {
  302. if (reference === SemanticAdaptationPackage.Literals.IMPORT__MODULE) {
  303. return getGlobalScope(context.eResource, reference)
  304. }
  305. val module = EcoreUtil2.getContainerOfType(context, SemanticAdaptation)
  306. var result = IScope.NULLSCOPE
  307. for (import : module.imports) {
  308. if (!import.module.eIsProxy)
  309. result = getModuleScope(context, reference, import.module, result)
  310. }
  311. result = getModuleScope(context, reference, module, result)
  312. return result//getDefinitionScope(context, reference, result)
  313. }
  314. def getModuleScope(EObject context, EReference reference, SemanticAdaptation module, IScope parent) {
  315. // FMUs and ports are visible
  316. val allDefinitions = module.elements.filter(FMU) + __getAllPorts(module)
  317. //println(allDefinitions)
  318. return Scopes.scopeFor(allDefinitions, parent)
  319. }
  320. /*def getDefinitionScope(EObject context, EReference reference, IScope parent) {
  321. val containingDef = EcoreUtil2.getContainerOfType(context, Definition)
  322. if (containingDef === null) {
  323. return parent
  324. }
  325. return Scopes.scopeFor(containingDef.args, parent)
  326. }*/
  327. //class SemanticAdaptationScopeProvider extends AbstractGlobalScopeDelegatingScopeProvider {
  328. // override getScope(EObject context, EReference reference) {
  329. // if (reference === SemanticAdaptationPackage.Literals.IMPORT__MODULE) {
  330. // return super.getGlobalScope(context.eResource, reference)
  331. // }
  332. // val module = EcoreUtil2.getContainerOfType(context, Module)
  333. // var result = IScope.NULLSCOPE
  334. // for (import : module.imports) {
  335. // if (!import.module.eIsProxy)
  336. // result = getModuleScope(context, reference, import.module, result)
  337. // }
  338. // result = getModuleScope(context, reference, module, result)
  339. // return getDefinitionScope(context, reference, result)
  340. // }
  341. //
  342. // def getModuleScope(EObject context, EReference reference, Module module, IScope parent) {
  343. // val allDefinitions = module.statements.filter(Definition)
  344. // if (context instanceof FunctionCall) {
  345. // return Scopes.scopeFor(allDefinitions.filter[context.args.size == args.size], parent)
  346. // } else {
  347. // return Scopes.scopeFor(allDefinitions, parent)
  348. // }
  349. // }
  350. //
  351. // def getDefinitionScope(EObject context, EReference reference, IScope parent) {
  352. // val containingDef = EcoreUtil2.getContainerOfType(context, Definition)
  353. // if (containingDef === null) {
  354. // return parent
  355. // }
  356. // return Scopes.scopeFor(containingDef.args, parent)
  357. // }
  358. }