package org.xpect.xtext.lib.util; import java.io.IOException; import java.util.Deque; import java.util.LinkedList; import java.util.Stack; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.AbstractElement; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Action; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.GrammarUtil; import org.eclipse.xtext.Keyword; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.formatting.IFormatter; import org.eclipse.xtext.formatting.IFormatterExtension; import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch; import org.eclipse.xtext.nodemodel.ICompositeNode; import org.eclipse.xtext.nodemodel.ILeafNode; import org.eclipse.xtext.parsetree.reconstr.ITokenStream; import org.eclipse.xtext.serializer.acceptor.ISequenceAcceptor; import org.eclipse.xtext.serializer.acceptor.TokenStreamSequenceAdapter; import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic; @SuppressWarnings("restriction") public class FormattingSequenceAcceptor implements ISequenceAcceptor { private static class Event { private final AbstractElement grammarElement; private final EObject sementicElement; private final String token; private Event(EObject sementicElement, AbstractElement grammarElement, String token) { super(); this.sementicElement = sementicElement; this.grammarElement = grammarElement; this.token = token; } } public static interface IAcceptor { void accept(EObject semanticElement, EObject grammarElement, String token, boolean hidden); } private class Out implements ITokenStream { public void flush() throws IOException { } protected void write(EObject grammarElement, String value) { if (grammarElement instanceof AbstractElement) { Event first = queue.pollFirst(); AbstractElement firstGrammarElement = first.grammarElement; CrossReference ref = GrammarUtil.containingCrossReference(firstGrammarElement); if (ref != null) firstGrammarElement = ref; if (firstGrammarElement == grammarElement && first.token.equals(value)) { // System.out.println("OK!"); } else { GrammarElementTitleSwitch f = new GrammarElementTitleSwitch().showQualified().showAssignments(); System.out.println(f.apply(firstGrammarElement) + "<>" + f.apply((AbstractElement) grammarElement) + "; " + first.token + "<>" + value); } delegate.accept(first.sementicElement, first.grammarElement, value, false); } else { delegate.accept(null, grammarElement, value, true); } } public void writeHidden(EObject grammarElement, String value) throws IOException { write(grammarElement, value); } public void writeSemantic(EObject grammarElement, String value) throws IOException { write(grammarElement, value); } } private final IAcceptor delegate; private final ISequenceAcceptor formatter; private final Deque<Event> queue = new LinkedList<Event>(); private final Stack<EObject> semanticElements = new Stack<EObject>(); private final ITokenStream formatterTokenStream; public FormattingSequenceAcceptor(EObject obj, IFormatter formatter, ISerializationDiagnostic.Acceptor errors, boolean preserveWhitespace, IAcceptor delegate) { this.delegate = delegate; this.semanticElements.push(obj); Out out = new Out(); if (formatter instanceof IFormatterExtension) formatterTokenStream = ((IFormatterExtension) formatter).createFormatterStream(obj, null, out, preserveWhitespace); else formatterTokenStream = formatter.createFormatterStream(null, out, preserveWhitespace); this.formatter = new TokenStreamSequenceAdapter(formatterTokenStream, errors); } public void acceptAssignedCrossRefDatatype(RuleCall datatypeRC, String token, EObject value, int index, ICompositeNode node) { enqueue(datatypeRC, token); formatter.acceptAssignedCrossRefDatatype(datatypeRC, token, value, index, node); } public void acceptAssignedCrossRefEnum(RuleCall enumRC, String token, EObject value, int index, ICompositeNode node) { enqueue(enumRC, token); formatter.acceptAssignedCrossRefEnum(enumRC, token, value, index, node); } public void acceptAssignedCrossRefKeyword(Keyword kw, String token, EObject value, int index, ILeafNode node) { enqueue(kw, token); formatter.acceptAssignedCrossRefKeyword(kw, token, value, index, node); } public void acceptAssignedCrossRefTerminal(RuleCall terminalRC, String token, EObject value, int index, ILeafNode node) { enqueue(terminalRC, token); formatter.acceptAssignedCrossRefTerminal(terminalRC, token, value, index, node); } public void acceptAssignedDatatype(RuleCall datatypeRC, String token, Object value, int index, ICompositeNode node) { enqueue(datatypeRC, token); formatter.acceptAssignedDatatype(datatypeRC, token, value, index, node); } public void acceptAssignedEnum(RuleCall enumRC, String token, Object value, int index, ICompositeNode node) { enqueue(enumRC, token); formatter.acceptAssignedEnum(enumRC, token, value, index, node); } public void acceptAssignedKeyword(Keyword keyword, String token, Object value, int index, ILeafNode node) { enqueue(keyword, token); formatter.acceptAssignedKeyword(keyword, token, value, index, node); } public void acceptAssignedTerminal(RuleCall terminalRC, String token, Object value, int index, ILeafNode node) { enqueue(terminalRC, token); formatter.acceptAssignedTerminal(terminalRC, token, value, index, node); } public void acceptComment(AbstractRule rule, String token, ILeafNode node) { formatter.acceptComment(rule, token, node); } public void acceptUnassignedAction(Action action) { formatter.acceptUnassignedAction(action); } public void acceptUnassignedDatatype(RuleCall datatypeRC, String token, ICompositeNode node) { enqueue(datatypeRC, token); formatter.acceptUnassignedDatatype(datatypeRC, token, node); } public void acceptUnassignedEnum(RuleCall enumRC, String token, ICompositeNode node) { enqueue(enumRC, token); formatter.acceptUnassignedEnum(enumRC, token, node); } public void acceptUnassignedKeyword(Keyword keyword, String token, ILeafNode node) { enqueue(keyword, token); formatter.acceptUnassignedKeyword(keyword, token, node); } public void acceptUnassignedTerminal(RuleCall terminalRC, String token, ILeafNode node) { enqueue(terminalRC, token); formatter.acceptUnassignedTerminal(terminalRC, token, node); } public void acceptWhitespace(AbstractRule rule, String token, ILeafNode node) { formatter.acceptWhitespace(rule, token, node); } protected void enqueue(AbstractElement ele, String token) { queue.addLast(new Event(semanticElements.peek(), ele, token)); } public boolean enterAssignedAction(Action action, EObject semanticChild, ICompositeNode node) { semanticElements.push(semanticChild); return formatter.enterAssignedAction(action, semanticChild, node); } public boolean enterAssignedParserRuleCall(RuleCall rc, EObject semanticChild, ICompositeNode node) { semanticElements.push(semanticChild); return formatter.enterAssignedParserRuleCall(rc, semanticChild, node); } public void enterUnassignedParserRuleCall(RuleCall rc) { formatter.enterUnassignedParserRuleCall(rc); } public void finish() { formatter.finish(); } public void leaveAssignedAction(Action action, EObject semanticChild) { semanticElements.pop(); formatter.leaveAssignedAction(action, semanticChild); } public void leaveAssignedParserRuleCall(RuleCall rc, EObject semanticChild) { semanticElements.pop(); formatter.leaveAssignedParserRuleCall(rc, semanticChild); } public void leaveUnssignedParserRuleCall(RuleCall rc) { formatter.leaveUnssignedParserRuleCall(rc); } public void flush() { try { formatterTokenStream.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }