title: Eclipse editor keeps hanging when editing Xtend files ( 'updating editor state (sleeping)' )
body: <p>Recently, my Eclipse editor started becoming really sluggish when editing Xtend files. I am using Xtend in the context of the Xtext framework (which provides certain interfaces using Xtend). I thought it had something to do with my Eclipse installation, so I deleted it entirely off my MacBook and re-installed the newest version (Eclipse 2019-09). However, it was still really sluggish when editing Xtend files. It does this every few seconds (loading figure appears, it hangs for a few seconds after which it repeats this sequence). I notice that the Progress tab in my Eclipse editor shows the message 'updating editor state (sleeping)' after it stops hanging. It only happens with Xtend files (other files like java work just fine in Eclipse without hanging). The Xtend file I am working in is currently about 500 Lines of Codes. Not a small file, but could this be the reason my Eclipse IDE keeps hanging? Things I already tried to fix this hanging problem:</p>
  
  <ul>
  <li>Fully delete and re-install Eclipse on my MacBook (only installing the necessary plug-ins that I need: The Palladio PCM framework, and the Xtext Framework).</li>
  <li>Provide extra memory (up to 6000 MB) for the Eclipse environment and its VMs (using the memory parameters (XmX e.g.) in the eclipse.ini file).</li>
  <li>Suspend all validators in the Eclipse environment (disabling the option to override this).</li>
  </ul>
  
  <p>The weird thing is that it keeps telling 'updating editor state (sleeping)' after it stops hanging. This message appears for about 0.1 to 2 seconds. I think that disabling the 'editor state update' might resolve this problem, but I don't know where I can suspend this option. Does anyone have a clue on why my Eclipse IDE keeps hanging every few seconds when editing Xtend files?</p>
  
  <p>EDIT 9 December 2019:</p>
  
  <pre><code>/*
   * generated by Xtext 2.17.1
   */
  package org.xtext.example.mydsl.generator
  
  import org.eclipse.emf.ecore.resource.Resource
  import org.eclipse.xtext.generator.AbstractGenerator
  import org.eclipse.xtext.generator.IFileSystemAccess2
  import org.eclipse.xtext.generator.IGeneratorContext
  import org.xtext.example.mydsl.finalDsl.UserProfile
  import org.xtext.example.mydsl.finalDsl.Model
  import org.xtext.example.mydsl.finalDsl.ConceptualMethod
  import org.xtext.example.mydsl.finalDsl.Expression
  import org.xtext.example.mydsl.finalDsl.AdditionalExpressions
  import org.xtext.example.mydsl.finalDsl.RelationalOperator
  import org.xtext.example.mydsl.finalDsl.SingleLibraryBusinessMethodStatement
  import org.xtext.example.mydsl.finalDsl.SingleLibraryPersistenceMethodStatement
  import org.xtext.example.mydsl.finalDsl.SingleLibraryInterFaceMethodStatement
  import org.xtext.example.mydsl.finalDsl.IfStatements
  import org.xtext.example.mydsl.finalDsl.IfElseStatements
  import org.eclipse.emf.ecore.EcoreFactory
  import org.eclipse.emf.ecore.EPackage
  import org.eclipse.xtext.ISetup
  import org.eclipse.emf.ecore.EStructuralFeature
  import java.util.TreeMap
  import java.util.HashMap
  import java.util.Set
  import org.palladiosimulator.pcm.util.*
  import org.palladiosimulator.pcm.repository.impl.*
  import org.palladiosimulator.pcm.repository.BasicComponent
  import org.eclipse.emf.ecore.EClass
  import org.palladiosimulator.pcm.core.CoreFactory
  import org.palladiosimulator.pcm.repository.RepositoryFactory
  import org.palladiosimulator.pcm.seff.SeffFactory
  import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl
  import org.eclipse.emf.common.util.URI
  import com.google.inject.Injector
  import org.xtext.example.mydsl.FinalDslStandaloneSetup
  import org.eclipse.emf.ecore.resource.ResourceSet
  import com.google.inject.Injector;
  import org.eclipse.emf.ecore.util.EcoreUtil
  import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
  import org.palladiosimulator.pcm.seff.seff_performance.ParametricResourceDemand
  import org.palladiosimulator.pcm.seff.seff_performance.impl.ParametricResourceDemandImpl
  import org.palladiosimulator.pcm.seff.seff_performance.SeffPerformanceFactory
  import java.util.Collections
  import org.eclipse.emf.ecore.EObject
  import org.xtext.example.mydsl.finalDsl.ElseStatement
  import java.util.ArrayList
  import java.math.BigDecimal
  import org.xtext.example.mydsl.finalDsl.Statement
  import org.xtext.example.mydsl.finalDsl.RelationalOperator
  import org.xtext.example.mydsl.finalDsl.AdditionOperator
  import org.xtext.example.mydsl.finalDsl.MultiplicationOperator
  import org.xtext.example.mydsl.finalDsl.libraryInterFaceMethodStatementEnum
  
  /**
   * Generates code from your model files on save.
   * 
   * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
   */
  class FinalDslGenerator extends AbstractGenerator {
  
  
  override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context ) {
  
      // Method call to build and store PCM Palladio repository. Right click on the repository file
      // to create a .repository_diagram file to 'graphically' view and edit the repository accordingly.
      RepositoryBuilder(resource,fsa)
  
      // Method call to calculate the resource demands for the If/Else statements in the model according
      // to the specified probabilities in the user profiles.
      UserProfileEstimator(resource,fsa)
  
      // Method call to build and store your modeled DSL instance accordingly. Mind that this has nothing
      // to do with the creation of the PCM Palladio repository above, but it might come in handy if you want
      // to export your DSL instances (for use outside of the xText IDE environment).
      ModelXMLBuilder(resource)   
      }
  
  // Method for calculating the resource demands for the If/Else statements in the model according to the 
  // specified probabilities in the user profiles. The declared probabilities are mapped to the If/Else Statements
  // by using a set of for loops (see loops for elaboration documentation).
  def UserProfileEstimator (Resource resource,IFileSystemAccess2 fsa) {
  
      // Treemap of  &lt;String,Integer&gt; pairs describing the set of library functions and their resource demands. These
      // resource demands can later be substituted for resource demand sample data in order to calculate the resource
      // demand estimations for the performance models. 
      var TreeMap&lt;String,Integer&gt; resourceTable = new TreeMap
          resourceTable.put("Hash",120)
          resourceTable.put("Concatenate",1000)
          resourceTable.put("Average",60)
          resourceTable.put("Count",80)
          resourceTable.put("Today",80)
          resourceTable.put("Time",80)
          resourceTable.put("Random",80)
          resourceTable.put("Max",43)
          resourceTable.put("Min",45)
          resourceTable.put("Root",80)
          resourceTable.put("Square",80)
          resourceTable.put("ReadDatabase",43)
          resourceTable.put("Message",123)
          resourceTable.put("ErrorMessage",100)
          resourceTable.put("WarningMessage",43)
          resourceTable.put("WriteDatabase",78)
          resourceTable.put("DeleteFromDatabase",67)
          resourceTable.put("Log",40)
          resourceTable.put('&gt;',40)
          resourceTable.put('&lt;&gt;',40)
          resourceTable.put('&lt;',40)
          resourceTable.put('=&gt;',40)
          resourceTable.put('&lt;=',40)
          resourceTable.put('==',40)
          resourceTable.put('in',40)
          resourceTable.put("+",40)
          resourceTable.put("-",40) 
          resourceTable.put("OR",40)
          resourceTable.put("*",40)
          resourceTable.put("/",40)
          resourceTable.put("AND",40)
  
      // check if statements
      var conceptualMethodDemandList = newArrayList
      var ifElseDemandList = newArrayList
  
      // TreeMap variable in order to store all the user profiles (indicated by the String variable in the list
      // and the corresponding resource demands (stored as Arraylist &lt;String&gt; arrays). The strings in this latter
      // Arraylist represent the probabilities for the If/Else statements in the model. Each of these probabilities
      // Contains the resource demand for the condition evaluation of the If-Statement, the If Statement body itself
      // and the Else statement. If one of these parts contains no Resource demand (if no library functions are present)
      // if an Else statement is not defined, the Resource Demand is zero.
      var TreeMap &lt;String, ArrayList &lt;String&gt; &gt; completeDemandList = new TreeMap
  
      // For loop to traverse through all declared user profiles in the model.
      for (userprofile : resource.allContents.toIterable.filter(UserProfile)) {   
  
          // For loop to traverse through all declared Conceptual Methods in the model. A conceptual method counter
          // variable is stored in order to keep track of which Conceptual Method is processed by the for loop. This
          // counter is used as the index for processing all user profile and resource demand data which are both stored
          // as arrays. 
          var conceptualMethodCounter = 0
  
          for (conceptualMethod : resource.allContents.toIterable.filter(ConceptualMethod)) {
  
          // For loop traversing through all If/Else statements in the corresponding conceptual methods declared in the model.
          // An ifElseStatementCounter variable is stored for the same reason as specified in the Conceptual Method for loop 
          // (see documentation above Conceptual Method for loop).
          var ifElseStatementCounter = 0
          for (ifElseStatement : conceptualMethod.eAllContents.toIterable.filter(IfElseStatements))  {
              var ifDemand = 0
              var elseDemand = 0
              var expressionDemand = 0
  
              // In the for-loop each if/Else statement is filtered for its If Statement part. This if Statement part is then filtered for
              // all three Library Function sorts. This happens for the functions in the expression part of the If Statement (containing the
              // condition that is evaluated), the actual If Statement part, and for the Else Statement part (in the case
              // an else statement is present in the If/Else statment).
              //  The dispatch method getDemand method is called for each library function statement together with the 
              // resourceTable variable containing all library functions and their resource demands. This dispatch method returns
              // the resource demand for the respective library function, after which this result is added to a 'Demand' variable
              // which contains the aggregate sum of all library functions for the calculated If/Else Statement part.
              for (ifStatement : ifElseStatement.eAllContents.toIterable.filter(IfStatements)){
  
                   for (expressionResourceStatement : ifStatement.expression.eAllContents.toIterable) {
  
                       switch(expressionResourceStatement){
                          SingleLibraryPersistenceMethodStatement,
                          SingleLibraryInterFaceMethodStatement,
                          SingleLibraryBusinessMethodStatement, 
                          RelationalOperator,
                          AdditionOperator,
                          MultiplicationOperator:                         
                               expressionDemand += getDemand(expressionResourceStatement,resourceTable)
                          }             
                      }
  
              for (innerIfStatements : ifStatement.statements){
                   for (ifResourceStatement : innerIfStatements.eAllContents.toIterable) {
                       switch(ifResourceStatement){
                          SingleLibraryPersistenceMethodStatement,
                          SingleLibraryInterFaceMethodStatement,
                          SingleLibraryBusinessMethodStatement, 
                          RelationalOperator,
                          AdditionOperator,
                          MultiplicationOperator:
                               ifDemand += getDemand(ifResourceStatement,resourceTable)
                          }
                      }
                  }
  
              for (elseStatement : ifElseStatement.eAllContents.toIterable.filter(ElseStatement)){
                   for (elseResourceStatement : elseStatement.eAllContents.toIterable) {
                       switch(elseResourceStatement){
                          SingleLibraryPersistenceMethodStatement,
                          SingleLibraryInterFaceMethodStatement,
                          SingleLibraryBusinessMethodStatement, 
                          RelationalOperator,
                          AdditionOperator,
                          MultiplicationOperator:
                               elseDemand += getDemand(elseResourceStatement,resourceTable)
                          }
                      }
                  }
                  // end of IfStatements for loop
              }
  
          // Add the resource demands of the evaluationDemand variable to the ifElseDemandList variable containing the resource demands
          // for the If/Else statement that is currently processed in the for-loop.
          ifElseDemandList.add("EvaluationDemands" + (conceptualMethodCounter+1).toString + "." + (ifElseStatementCounter+1).toString + ": " + BigDecimal.valueOf(expressionDemand))
  
          // Add the resource demands of the ifDemand and elseDemand variable to the ifElseDemandList variable containing the resource demands
          // for the If/Else statement that is currently processed in the for-loop. In the case the probability is declared in the user profile 
          // as zero (.0), the probability is assumed to be .50. The second if-statement below filters and handles these cases accordingly.
          if (userprofile.probabilitysets.get(conceptualMethodCounter).probability.get(ifElseStatementCounter) != 0) {
              ifElseDemandList.add("IfStatementDemands" + (conceptualMethodCounter+1).toString + "." + (ifElseStatementCounter+1).toString + ": " + BigDecimal.valueOf(ifDemand*userprofile.probabilitysets.get(conceptualMethodCounter).probability.get(ifElseStatementCounter)))
              ifElseDemandList.add("ElseStatementDemands" + (conceptualMethodCounter+1).toString + "." + (ifElseStatementCounter+1).toString + ": " + BigDecimal.valueOf(elseDemand*(1-userprofile.probabilitysets.get(conceptualMethodCounter).probability.get(ifElseStatementCounter))))
              }
  
          if (userprofile.probabilitysets.get(conceptualMethodCounter).probability.get(ifElseStatementCounter) == 0) {            
              ifElseDemandList.add("IfStatementDemands" + (conceptualMethodCounter+1).toString + "." + (ifElseStatementCounter+1).toString + ": " + BigDecimal.valueOf(ifDemand*0.5))
              ifElseDemandList.add("ElseStatementDemands" + (conceptualMethodCounter+1).toString + "." + (ifElseStatementCounter+1).toString + ": " + BigDecimal.valueOf(elseDemand*0.5))
              }
  
  
          // Once all the parts of the If/Else statement in the for-loop are processed, the resulting list of resource demands for the If/Else statement (stored
          // in the ifElseDemandList variable) are added to the conceptualMethodDemandList variable containing the resource demands for all
          // If/Else statements in the conceptual method. Next the ifElseDemandList is cleared and the ifElseStatementCounter is incremented in order for the next for-loop
          // iteration to process the next If/Else statement of the conceptual method.
          conceptualMethodDemandList.add('''
                                      «ifElseDemandList.clone.toString»
                                      ''')
          ifElseDemandList.clear
          ifElseStatementCounter++
      }
  
      // Once all the If/Else statements in the for-loop are processed, the resulting list of resource demands for all If/Else statements (stored
      // in the conceptualMethodDemandList variable) are added to the completeDemandList variable containing the resource demands for all
      // conceptual methods and user profiles.
      conceptualMethodCounter++
  
      completeDemandList.put('''
                      «userprofile.name»
                      ''',conceptualMethodDemandList.clone() as ArrayList&lt;String&gt;)
  
      }
  
      conceptualMethodDemandList.clear
      }
  
  
      // The completeDemandList variable containing all resource demands according to all the specified user profiles, are
      // stored below in a text file.
      fsa.generateFile(
          "IfElseStatementsDemands.txt",
           completeDemandList.toString)
  }
  
  // Dispatch method for looking up the resource demand of a library business function in a TreeMap variable
  // containing the resource demands for all library functions.
  def dispatch getDemand (SingleLibraryBusinessMethodStatement statement, TreeMap&lt;String,Integer&gt; resourceTable) {
          return resourceTable.get(statement.libraryFunction.toString)
      }
  
  // Dispatch method for looking up the resource demand of a library interface function in a TreeMap variable
  // containing the resource demands for all library functions.
  def dispatch getDemand (SingleLibraryInterFaceMethodStatement statement, TreeMap&lt;String,Integer&gt; resourceTable) {
          return resourceTable.get(statement.libraryFunction.toString)
      }
  
  // Dispatch method for looking up the resource demand of a library persistence function in a TreeMap variable
  // containing the resource demands for all library functions.
  def dispatch getDemand (SingleLibraryPersistenceMethodStatement statement, TreeMap&lt;String,Integer&gt; resourceTable) {
          return resourceTable.get(statement.libraryFunction.toString)
      }
  
  def dispatch getDemand (RelationalOperator statement, TreeMap&lt;String,Integer&gt; resourceTable) {
          return resourceTable.get(statement.operator.toString)
  }
  
  def dispatch getDemand (AdditionOperator statement, TreeMap&lt;String,Integer&gt; resourceTable) {
      return resourceTable.get(statement.operator.toString)
  }
  
  def dispatch getDemand (MultiplicationOperator statement, TreeMap&lt;String,Integer&gt; resourceTable) {
      return resourceTable.get(statement.operator.toString)
  }
  
  def RepositoryBuilder (Resource resource,IFileSystemAccess2 fsa) {
  
      var repository = RepositoryFactory.eINSTANCE.createRepository
      repository.setEntityName("Repository for Functional Model")
  
      var myInterface = RepositoryFactory.eINSTANCE.createOperationInterface()
      myInterface.setEntityName("My Interface")
      repository.getInterfaces__Repository().add(myInterface); //add first class entity
  
      var opProvRole = RepositoryFactory.eINSTANCE.createOperationProvidedRole()
      opProvRole.setEntityName("Provided Role of Basic Component")
  
      // set the interface for the role:
      opProvRole.setProvidedInterface__OperationProvidedRole(myInterface)
  
      for (element : resource.allContents.toIterable.filter(ConceptualMethod))
      {   
          var component = RepositoryFactory.eINSTANCE.createBasicComponent()
          component.setEntityName(element.name)
          ConceptualClass2SEFF(component, element)
          // set/add the role for basic component:
          component.getProvidedRoles_InterfaceProvidingEntity().add(opProvRole)
          repository.getComponents__Repository().add(component)  //add first class entity
      }
  
      var storeRepositoryURI =  URI.createURI(resource.URI.trimSegments(1).toString + "/src-gen/TestRepository.repository")
      var result = new XMLResourceImpl(storeRepositoryURI)
          result.getContents().add(repository)
          result.save(null)
      }
  
  def ConceptualClass2SEFF (BasicComponent component, ConceptualMethod conceptualmethod) {
      for (statement : conceptualmethod.eAllContents.toIterable.filter(SingleLibraryPersistenceMethodStatement)) 
      { 
          var seff = SeffFactory.eINSTANCE.createResourceDemandingSEFF()
          var internalAction = SeffFactory.eINSTANCE.createInternalAction()
          internalAction.entityName = statement.libraryFunction.toString
          internalAction.resourceDemand_Action.add(SeffPerformanceFactory.eINSTANCE.createParametricResourceDemand)
          seff.steps_Behaviour.add(internalAction)
          component.serviceEffectSpecifications__BasicComponent.add(seff)    
      }
  
      for (statement : conceptualmethod.eAllContents.toIterable.filter(SingleLibraryInterFaceMethodStatement)) 
      { 
          var seff = SeffFactory.eINSTANCE.createResourceDemandingSEFF()
          var internalAction = SeffFactory.eINSTANCE.createInternalAction()
          internalAction.entityName = statement.libraryFunction.toString
          internalAction.resourceDemand_Action.add(SeffPerformanceFactory.eINSTANCE.createParametricResourceDemand)
          seff.steps_Behaviour.add(internalAction)
          component.serviceEffectSpecifications__BasicComponent.add(seff)    
      }
  
      for (statement : conceptualmethod.eAllContents.toIterable.filter(SingleLibraryBusinessMethodStatement)) 
      { 
          var seff = SeffFactory.eINSTANCE.createResourceDemandingSEFF()
          var internalAction = SeffFactory.eINSTANCE.createInternalAction()
          internalAction.entityName = statement.libraryFunction.toString
          internalAction.resourceDemand_Action.add(SeffPerformanceFactory.eINSTANCE.createParametricResourceDemand)
          seff.steps_Behaviour.add(internalAction)
          component.serviceEffectSpecifications__BasicComponent.add(seff)    
      }
  }
  
  def ModelXMLBuilder (Resource dslInstance) {
      var injector = new FinalDslStandaloneSetup().createInjectorAndDoEMFRegistration()
      var resourceSet = injector.getInstance(ResourceSet)
  
      dslInstance.load(null)
      EcoreUtil.resolveAll(resourceSet)
  
      var storeXmiURI =  URI.createURI(dslInstance.URI.trimSegments(1).toString + "/src-gen/DslModel.xmi")
  
      var xmiResource = resourceSet.createResource(storeXmiURI)
          xmiResource.getContents().add(dslInstance.getContents().get(0))
          xmiResource.save(null)
      }
  }
  </code></pre>