blob: f2083441645ed1db16395fbfa004ce7aa30dfe44 [file] [log] [blame]
package org.eclipse.wst.jsdt.web.ui.internal.format;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IDocumentPartitioningListener;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy;
import org.eclipse.jface.text.formatter.FormattingContextProperties;
import org.eclipse.jface.text.formatter.IFormattingContext;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.wst.jsdt.core.ICompilationUnit;
import org.eclipse.wst.jsdt.core.IJavaProject;
import org.eclipse.wst.jsdt.core.JavaCore;
import org.eclipse.wst.jsdt.core.JavaModelException;
import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;
import org.eclipse.wst.jsdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.wst.jsdt.internal.formatter.DefaultCodeFormatter;
import org.eclipse.wst.jsdt.web.core.internal.java.IJSPTranslation;
import org.eclipse.wst.jsdt.web.core.internal.java.JSPTranslationAdapter;
import org.eclipse.wst.jsdt.web.core.internal.java.JSPTranslationExtension;
import org.eclipse.wst.jsdt.web.core.internal.java.JSPTranslationUtil;
import org.eclipse.wst.jsdt.web.core.internal.java.ModelIrritant;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
public class FormattingStrategyJSPJava extends ContextBasedFormattingStrategy {
/** Documents to be formatted by this strategy */
private final LinkedList fDocuments = new LinkedList();
/** Partitions to be formatted by this strategy */
private final LinkedList fPartitions = new LinkedList();
private static final int regionStartIndentLevel = 1;
private int startIndentLevel;
/**
* Creates a new java formatting strategy.
*/
public FormattingStrategyJSPJava() {
super();
}
// private class partitionerAttachedChangeListener implements IDocumentPartitioningListener {
// private IDocument attachedDoc;
//
// partitionerAttachedChangeListener(IDocument attachedDoc) {
// this.attachedDoc = attachedDoc;
// }
//
// public void documentPartitioningChanged(IDocument document) {
// if (document == attachedDoc && document instanceof IDocumentExtension3) {
// IDocumentExtension3 extension3 = (IDocumentExtension3) document;
// String[] partitionings = extension3.getPartitionings();
// Vector partitioners = new Vector();
// for (int i = 0; i < partitionings.length; i++) {
// IDocumentPartitioner partitioner = extension3.getDocumentPartitioner(partitionings[i]);
// if (partitioner instanceof StructuredTextPartitioner) {
// IDOMModel xmlModel = null;
// try {
// xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(document);
// xmlModel.reinit();
// } catch (Exception e) {
// System.out.println("Exception in adapter for model re-init" + e);
// } finally {
// if (xmlModel != null) {
// xmlModel.releaseFromRead();
// }
// }
// document.removeDocumentPartitioningListener(this);
// }
// }
// }
// }
// }
/*
* @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#format()
*/
public void format() {
super.format();
final IStructuredDocument document = (IStructuredDocument) fDocuments.removeFirst();
final TypedPosition partition = (TypedPosition) fPartitions.removeFirst();
if (document != null) {
try {
//JSPTranslationUtil translationUtil = new JSPTranslationUtil(document);
JSPTranslationExtension translation = getTranslation(document);
ICompilationUnit cu = translation.getCompilationUnit();
if (cu != null) {
String cuSource = cu.getSource();
int javaStart = translation.getJsOffset(partition.getOffset());
int javaLength = partition.getLength();
TextEdit edit = CodeFormatterUtil.format2(CodeFormatter.K_COMPILATION_UNIT, cuSource, javaStart, javaLength, startIndentLevel, TextUtilities.getDefaultLineDelimiter(document), getPreferences());
IDocument doc = translation.getJavaDocument();
edit.apply(doc);
String replaceText = TextUtilities.getDefaultLineDelimiter(document) + getIndentationString(getPreferences(), startIndentLevel) + (doc.get(edit.getOffset(), edit.getLength())).trim() + TextUtilities.getDefaultLineDelimiter(document);
/*
* this is necisary since SSE disconnects document
* partitioners.. Because of that, the replaced regions are
* considered 'partitionless' when the linestyle provider
* trys to color them.
*
*/
document.replaceText(document, partition.getOffset(), partition.getLength(), replaceText);
document.addDocumentPartitioningListener(new ModelIrritant(document));
}
} catch (BadLocationException e) {
} catch (JavaModelException e) {
}
}
}
public JSPTranslationExtension getTranslation(IStructuredDocument document) {
JSPTranslationExtension tran=null;
IDOMModel xmlModel=null;
try {
xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(document);
IDOMDocument xmlDoc = xmlModel.getDocument();
JSPTranslationAdapter translationAdapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
if (translationAdapter != null) {
tran = translationAdapter.getJSPTranslation();
}
} finally {
if (xmlModel != null) {
xmlModel.releaseFromRead();
}
}
return tran;
}
/*
* @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStarts(org.eclipse.jface.text.formatter.IFormattingContext)
*/
public void formatterStarts(final IFormattingContext context) {
fPartitions.addLast(context.getProperty(FormattingContextProperties.CONTEXT_PARTITION));
fDocuments.addLast(context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM));
startIndentLevel = regionStartIndentLevel + 0;
Map projectOptions = (Map) context.getProperty(FormattingContextProperties.CONTEXT_PREFERENCES);
if (projectOptions == null) {
IDocument doc = (IDocument) context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM);
context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, getProjectOptions(doc));
}
super.formatterStarts(context);
}
/*
* @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStops()
*/
public void formatterStops() {
super.formatterStops();
fPartitions.clear();
fDocuments.clear();
startIndentLevel = 0;
}
public String getIndentationString(Map options, int indentationLevel) {
DefaultCodeFormatter formatter = new DefaultCodeFormatter(options);
return formatter.createIndentationString(indentationLevel);
}
private Map getProjectOptions(IDocument baseDocument) {
IJavaProject javaProject = null;
IDOMModel xmlModel = null;
Map options = null;
try {
xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(baseDocument);
String baseLocation = xmlModel.getBaseLocation();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IPath filePath = new Path(baseLocation);
IProject project = null;
if (filePath.segmentCount() > 0) {
project = root.getProject(filePath.segment(0));
}
if (project != null) javaProject = JavaCore.create(project);
} finally {
if (xmlModel != null) {
xmlModel.releaseFromRead();
}
}
if (javaProject != null) {
options = javaProject.getOptions(true);
}
return options;
}
private Map getNodeFromRegion(IDocument baseDocument) {
IJavaProject javaProject = null;
IDOMModel xmlModel = null;
Map options = null;
try {
xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(baseDocument);
} finally {
if (xmlModel != null) {
xmlModel.releaseFromRead();
}
}
if (javaProject != null) {
options = javaProject.getOptions(true);
}
return options;
}
}