docs: protected void generateDocumentationProviderImpl() {
  		TypeReference etype = null;
  		final LinkedList<Grammar> grammars = new LinkedList<>();
  		grammars.addAll(getGrammar().getUsedGrammars());
  		while (etype == null && !grammars.isEmpty()) {
  			final Grammar grammar = grammars.removeFirst();
  			grammars.addAll(grammar.getUsedGrammars());
  			final String gbase = getNaming().getRuntimeBasePackage(grammar);
  			final String providerClassname = gbase + ".documentation." //$NON-NLS-1$
  					+ GrammarUtil.getSimpleName(grammar) + "DocumentationProvider"; //$NON-NLS-1$
  			try {
  				getClass().getClassLoader().loadClass(providerClassname);
  				etype = new TypeReference(providerClassname);
  			} catch (Throwable exception) {
  				//
  			}
  		}
  		if (etype == null) {
  			etype = new TypeReference(MultiLineCommentDocumentationProvider.class);
  		}
  		final TypeReference extendType = etype;
  		final TypeReference provider = getDocumentationProviderImpl();
  		final StringConcatenationClient content = new StringConcatenationClient() {
  			@Override
  			protected void appendTo(TargetStringConcatenation it) {
  				it.append("/** Provider a documentation string."); //$NON-NLS-1$
  				it.newLine();
  				it.append(" */"); //$NON-NLS-1$
  				it.newLine();
  				it.append("public class "); //$NON-NLS-1$
  				it.append(provider.getSimpleName());
  				it.append(" extends "); //$NON-NLS-1$
  				it.append(extendType);
  				it.append(" {"); //$NON-NLS-1$
  				it.newLineIfNotEmpty();
  				it.newLine();
  				it.append("\tpublic String getDocumentation("); //$NON-NLS-1$
  				it.append(EObject.class);
  				it.append(" o) {"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t// Get the documentation from the Xtext grammar hidden nodes."); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\tString text = super.getDocumentation(o);"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\tif (text == null) {"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t// Get the grammar from the Ecore model element."); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\tif (o instanceof "); //$NON-NLS-1$
  				it.append(EModelElement.class);
  				it.append(") {"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\ttext = "); //$NON-NLS-1$
  				it.append(EcoreUtil.class);
  				it.append(".getDocumentation(("); //$NON-NLS-1$
  				it.append(EModelElement.class);
  				it.append(") o);"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t}"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\tif (text == null) {"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\t// Get the grammar from the code builder extension."); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\t"); //$NON-NLS-1$
  				it.append(DocumentationAdapter.class);
  				it.append(" adapter = ("); //$NON-NLS-1$
  				it.append(DocumentationAdapter.class);
  				it.append(") "); //$NON-NLS-1$
  				it.append(EcoreUtil.class);
  				it.append(".getAdapter("); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\t\t\to.eAdapters(), "); //$NON-NLS-1$
  				it.append(DocumentationAdapter.class);
  				it.append(".class);"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\tif (adapter != null) {"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\t\treturn adapter.getDocumentation();"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t\t}"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t\t}"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\t}"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t\treturn text;"); //$NON-NLS-1$
  				it.newLine();
  				it.append("\t}"); //$NON-NLS-1$
  				it.newLine();
  				it.append("}"); //$NON-NLS-1$
  				it.newLineIfNotEmpty();
  				it.newLine();
  			}
  
  		};
  		final JavaFileAccess createJavaFile = getFileAccessFactory().createJavaFile(provider, content);
  		createJavaFile.writeTo(getSrcGen());
  	}