docs: public static EObject findActualSemanticObjectFor(/* @Nullable */ INode node) {
  		if (node == null)
  			return null;
  		if (node.hasDirectSemanticElement())
  			return node.getSemanticElement();
  		EObject grammarElement = node.getGrammarElement();
  		ICompositeNode parent = node.getParent();
  		if (grammarElement == null)
  			return findActualSemanticObjectFor(parent);
  		Assignment assignment = GrammarUtil.containingAssignment(grammarElement);
  		if (assignment != null) {
  			if (GrammarUtil.isEObjectFragmentRule(GrammarUtil.containingRule(assignment))) {
  				EObject result = findActualSemanticObjectInChildren(node, grammarElement);
  				if (result != null)
  					return result;
  			}
  			if (parent.hasDirectSemanticElement())
  				return findActualSemanticObjectFor(parent);
  			INode sibling = parent.getFirstChild();
  			while(!sibling.equals(node)) {
  				EObject siblingGrammarElement = sibling.getGrammarElement();
  				if (siblingGrammarElement != null && GrammarUtil.containingAssignment(siblingGrammarElement) == null) {
  					if (GrammarUtil.isEObjectRuleCall(siblingGrammarElement)) {
  						return findActualSemanticObjectFor(sibling);
  					}
  					if (siblingGrammarElement.eClass() == XtextPackage.Literals.ACTION) {
  						return findActualSemanticObjectFor(sibling);
  					}
  				}
  				sibling = sibling.getNextSibling();
  			}
  		} else if (!GrammarUtil.isEObjectFragmentRuleCall(grammarElement)) {
  			EObject result = findActualSemanticObjectInChildren(node, grammarElement);
  			if (result != null)
  				return result;
  		}
  		return findActualSemanticObjectFor(parent);
  	}