Skip to content

Implementing annexes

AaronGreenhouse edited this page Oct 2, 2020 · 7 revisions

Global scope must be fully implemented for the annex, delegate to core global scope provider.

Outline Tree Providers

The outline tree provider for the annex sublanguage needs to extend from BackgroundOutlineTreeProvider (not DefaultOutlineTreeProvider). This allows the outline tree to be build in a separate thread from the UI thread. The main AADL outline tree provider runs in the background, so the annex threads must also.

You need to make sure the label provider for your sublanguage implements ILabelProviderImageDescriptorExtension. I'm pretty sure this happens for free in Xtext as org.eclipse.xtext.ui.label.AbstractLabelProvider implements it.

Converting an outline tree provider to extend from BackgroundOutlineTreeProvider takes a little work because it does not use the PolymorphicDispatcher hack that DefaultOutlineTreeProvider uses. Instead its createChildren() method delegates to a trio of methods:

  • internalCreateChildren(DocumentRootNode parentNode, EObject modelElement)
  • internalCreateChildren(EStructuralFeatureNode parentNode, EObject modelElement)
  • internalCreateChildren(IOutlineNode parentNode, EObject modelElement)

When updating ErrorModelOutlineTreeProvider, we handled this situation by

  1. Changing _createChildren(DocumentRootNode parentNode, EMV2Root emv2Root) into internalCreateChildren(DocumentRootNode parentNode, EObject modelElement):
	protected void _createChildren(DocumentRootNode parentNode, EMV2Root emv2Root) {
		if (emv2Root.getLibrary() != null) {
			createNode(parentNode, emv2Root.getLibrary());
		} else {
			emv2Root.getSubclauses().forEach(subclause -> createNode(parentNode, subclause));
		}
	}

to

	protected void internalCreateChildren(final DocumentRootNode parentNode, final EObject modelElement) {
		if (modelElement instanceof EMV2Root) {
			final EMV2Root emv2Root = (EMV2Root) modelElement;
			if (emv2Root.getLibrary() != null) {
				createNode(parentNode, emv2Root.getLibrary());
			} else {
				emv2Root.getSubclauses().forEach(subclause -> createNode(parentNode, subclause));
			}
		} else {
			super.internalCreateChildren(parentNode, modelElement);
		}
	}
  1. For all the _createChildren(IOutlineNode, ...) methods, we implemented internalCreateChildren(IOutlineNode parentNode, EObject modelElement) to perform the polymorphic dispatch tests directly:
	@Override
	protected void internalCreateChildren(final IOutlineNode parentNode, final EObject modelElement) {
		if (parentNode instanceof ErrorPropagationsOutlineNode) {
			_createChildren((ErrorPropagationsOutlineNode) parentNode, (ErrorModelSubclause) modelElement);
		} else if (parentNode instanceof ComponentErrorBehaviorOutlineNode) {
			_createChildren((ComponentErrorBehaviorOutlineNode) parentNode, (ErrorModelSubclause) modelElement);
		} else if (parentNode instanceof CompositeErrorBehaviorOutlineNode) {
			_createChildren((CompositeErrorBehaviorOutlineNode) parentNode, (ErrorModelSubclause) modelElement);
		} else if (parentNode instanceof ConnectionErrorOutlineNode) {
			_createChildren((ConnectionErrorOutlineNode) parentNode, (ErrorModelSubclause) modelElement);
		} else if (parentNode instanceof PropagationPathsOutlineNode) {
			_createChildren((PropagationPathsOutlineNode) parentNode, (ErrorModelSubclause) modelElement);
		} else if (parentNode instanceof ErrorTypesOutlineNode) {
			_createChildren((ErrorTypesOutlineNode) parentNode, (ErrorModelLibrary) modelElement);
		} else {
			if (modelElement instanceof DefaultAnnexLibrary) {
				_createChildren(parentNode, (DefaultAnnexLibrary) modelElement);
			} else if (modelElement instanceof DefaultAnnexSubclause) {
				_createChildren(parentNode, (DefaultAnnexSubclause) modelElement);
			} else if (modelElement instanceof ErrorModelSubclause) {
				_createChildren(parentNode, (ErrorModelSubclause) modelElement);
			} else if (modelElement instanceof ErrorBehaviorStateMachine) {
				_createChildren(parentNode, (ErrorBehaviorStateMachine) modelElement);
			} else if (modelElement instanceof ErrorModelLibrary) {
				_createChildren(parentNode, (ErrorModelLibrary) modelElement);
			}
		}
	}

Of course, if the _createChildren() are very few and very simple, it makes more sense to just inline the methods in to the new internalCreateChildren() method.

All the _isLeaf() methods can be merged into the isLeaf() method:

	protected boolean _isLeaf(TypeSet typeSet) {
		return true;
	}

	protected boolean _isLeaf(TypeTransformation typeTransformation) {
		return true;
	}

	protected boolean _isLeaf(TypeMapping typeMapping) {
		return true;
	}

	protected boolean _isLeaf(ErrorPropagation errorPropagation) {
		return true;
	}

	protected boolean _isLeaf(ErrorFlow errorFlow) {
		return true;
	}

	protected boolean _isLeaf(PropagationPath propagationPath) {
		return true;
	}

	protected boolean _isLeaf(ErrorBehaviorEvent errorBehaviorEvent) {
		return true;
	}

	protected boolean _isLeaf(ErrorBehaviorState errorBehaviorState) {
		return true;
	}

	protected boolean _isLeaf(ErrorBehaviorTransition errorBehaviorTransition) {
		return true;
	}

	protected boolean _isLeaf(OutgoingPropagationCondition outgoingPropagationCondition) {
		return true;
	}

	protected boolean _isLeaf(ErrorDetection errorDetection) {
		return true;
	}

	protected boolean _isLeaf(ErrorStateToModeMapping errorStateToModeMapping) {
		return true;
	}

	protected boolean _isLeaf(CompositeState compositeState) {
		return true;
	}

became

	protected boolean isLeaf(final EObject modelElement) {
		return modelElement instanceof TypeSet || modelElement instanceof TypeTransformation
				|| modelElement instanceof TypeMapping || modelElement instanceof ErrorPropagation
				|| modelElement instanceof ErrorFlow || modelElement instanceof PropagationPath
				|| modelElement instanceof ErrorBehaviorEvent || modelElement instanceof ErrorBehaviorState
				|| modelElement instanceof ErrorBehaviorTransition
				|| modelElement instanceof OutgoingPropagationCondition || modelElement instanceof ErrorDetection
				|| modelElement instanceof ErrorStateToModeMapping || modelElement instanceof CompositeState;
	}