| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.jsdt.internal.ui.compare; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.Map; |
| |
| import org.eclipse.compare.HistoryItem; |
| import org.eclipse.compare.ITypedElement; |
| import org.eclipse.compare.ResourceNode; |
| import org.eclipse.core.filebuffers.ITextFileBuffer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFileState; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.RewriteSessionEditProcessor; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.text.edits.MultiTextEdit; |
| import org.eclipse.text.edits.TextEdit; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.part.FileEditorInput; |
| import org.eclipse.ui.texteditor.IDocumentProvider; |
| import org.eclipse.wst.jsdt.core.IJavaScriptElement; |
| import org.eclipse.wst.jsdt.core.IJavaScriptProject; |
| import org.eclipse.wst.jsdt.core.IJavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.IMember; |
| import org.eclipse.wst.jsdt.core.ISourceRange; |
| import org.eclipse.wst.jsdt.core.JavaScriptModelException; |
| import org.eclipse.wst.jsdt.core.dom.AST; |
| import org.eclipse.wst.jsdt.core.dom.ASTNode; |
| import org.eclipse.wst.jsdt.core.dom.ASTParser; |
| import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.dom.TypeDeclaration; |
| import org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.wst.jsdt.internal.corext.dom.NodeFinder; |
| import org.eclipse.wst.jsdt.internal.corext.util.Strings; |
| import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; |
| import org.eclipse.wst.jsdt.internal.ui.actions.SelectionConverter; |
| import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaEditor; |
| |
| /** |
| * Base class for the "Replace with local history" |
| * and "Add from local history" actions. |
| */ |
| abstract class JavaHistoryActionImpl /* extends Action implements IActionDelegate*/ { |
| |
| private boolean fModifiesFile; |
| private ISelection fSelection; |
| |
| JavaHistoryActionImpl(boolean modifiesFile) { |
| fModifiesFile= modifiesFile; |
| } |
| |
| ISelection getSelection() { |
| return fSelection; |
| } |
| |
| final IFile getFile(Object input) { |
| return JavaElementHistoryPageSource.getInstance().getFile(input); |
| } |
| |
| final ITypedElement[] buildEditions(ITypedElement target, IFile file) { |
| |
| // setup array of editions |
| IFileState[] states= null; |
| // add available editions |
| try { |
| states= file.getHistory(null); |
| } catch (CoreException ex) { |
| JavaScriptPlugin.log(ex); |
| } |
| |
| int count= 1; |
| if (states != null) |
| count+= states.length; |
| |
| ITypedElement[] editions= new ITypedElement[count]; |
| editions[0]= new ResourceNode(file); |
| if (states != null) |
| for (int i= 0; i < states.length; i++) |
| editions[i+1]= new HistoryItem(target, states[i]); |
| return editions; |
| } |
| |
| final Shell getShell() { |
| if (fEditor != null) |
| return fEditor.getEditorSite().getShell(); |
| return JavaScriptPlugin.getActiveWorkbenchShell(); |
| } |
| |
| /** |
| * Tries to find the given element in a working copy. |
| */ |
| final IJavaScriptElement getWorkingCopy(IJavaScriptElement input) { |
| // TODO: With new working copy story: original == working copy. |
| // Note that the previous code could result in a reconcile as side effect. Should check if that |
| // is still required. |
| return input; |
| } |
| |
| final ASTNode getBodyContainer(JavaScriptUnit root, IMember parent) throws JavaScriptModelException { |
| ISourceRange sourceRange= parent.getNameRange(); |
| ASTNode parentNode= NodeFinder.perform(root, sourceRange); |
| do { |
| if (parentNode instanceof TypeDeclaration ) |
| return parentNode; |
| parentNode= parentNode.getParent(); |
| } while (parentNode != null); |
| return null; |
| } |
| |
| /** |
| * Returns true if the given file is open in an editor. |
| */ |
| final boolean beingEdited(IFile file) { |
| IDocumentProvider dp= JavaScriptPlugin.getDefault().getCompilationUnitDocumentProvider(); |
| FileEditorInput input= new FileEditorInput(file); |
| return dp.getDocument(input) != null; |
| } |
| |
| /** |
| * Returns an IMember or null. |
| */ |
| final IMember getEditionElement(ISelection selection) { |
| |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection ss= (IStructuredSelection) selection; |
| if (ss.size() == 1) { |
| Object o= ss.getFirstElement(); |
| if (o instanceof IMember) { |
| IMember m= (IMember) o; |
| if (m.exists() && !m.isBinary() && JavaStructureCreator.hasEdition(m)) |
| return m; |
| } |
| } |
| } |
| return null; |
| } |
| |
| final boolean isEnabled(IFile file) { |
| if (file == null || ! file.exists()) |
| return false; |
| if (fModifiesFile) { |
| // without validate/edit we would do this: |
| // return !file.isReadOnly(); |
| // with validate/edit we have to return true |
| return true; |
| } |
| return true; |
| } |
| |
| boolean isEnabled(ISelection selection) { |
| IMember m= getEditionElement(selection); |
| if (m == null) |
| return false; |
| IFile file= getFile(m); |
| if (!isEnabled(file)) |
| return false; |
| return true; |
| } |
| |
| void applyChanges(ASTRewrite rewriter, final IDocument document, final ITextFileBuffer textFileBuffer, Shell shell, boolean inEditor, Map options) |
| throws CoreException, InvocationTargetException, InterruptedException { |
| |
| |
| MultiTextEdit edit= new MultiTextEdit(); |
| try { |
| TextEdit res= rewriter.rewriteAST(document, options); |
| edit.addChildren(res.removeChildren()); |
| } catch (IllegalArgumentException e) { |
| JavaScriptPlugin.log(e); |
| } |
| |
| try { |
| new RewriteSessionEditProcessor(document, edit, TextEdit.UPDATE_REGIONS).performEdits(); |
| } catch (BadLocationException e) { |
| JavaScriptPlugin.log(e); |
| } |
| |
| IRunnableWithProgress r= new IRunnableWithProgress() { |
| public void run(IProgressMonitor pm) throws InvocationTargetException { |
| try { |
| textFileBuffer.commit(pm, false); |
| } catch (CoreException ex) { |
| throw new InvocationTargetException(ex); |
| } |
| } |
| }; |
| |
| if (inEditor) { |
| // we don't show progress |
| r.run(new NullProgressMonitor()); |
| } else { |
| PlatformUI.getWorkbench().getProgressService().run(true, false, r); |
| } |
| } |
| |
| static String trimTextBlock(String content, String delimiter, IJavaScriptProject currentProject) { |
| if (content != null) { |
| String[] lines= Strings.convertIntoLines(content); |
| if (lines != null) { |
| Strings.trimIndentation(lines, currentProject); |
| return Strings.concatenate(lines, delimiter); |
| } |
| } |
| return null; |
| } |
| |
| final JavaEditor getEditor(IFile file) { |
| FileEditorInput fei= new FileEditorInput(file); |
| IWorkbench workbench= JavaScriptPlugin.getDefault().getWorkbench(); |
| IWorkbenchWindow[] windows= workbench.getWorkbenchWindows(); |
| for (int i= 0; i < windows.length; i++) { |
| IWorkbenchPage[] pages= windows[i].getPages(); |
| for (int x= 0; x < pages.length; x++) { |
| IEditorPart[] editors= pages[x].getDirtyEditors(); |
| for (int z= 0; z < editors.length; z++) { |
| IEditorPart ep= editors[z]; |
| if (ep instanceof JavaEditor) { |
| JavaEditor je= (JavaEditor) ep; |
| if (fei.equals(je.getEditorInput())) |
| return (JavaEditor) ep; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Executes this action with the given selection. |
| */ |
| public abstract void run(ISelection selection); |
| |
| //---- Action |
| |
| private JavaEditor fEditor; |
| private String fTitle; |
| private String fMessage; |
| |
| void init(JavaEditor editor, String title, String message) { |
| fEditor= editor; |
| fTitle= title; |
| fMessage= message; |
| } |
| |
| final JavaEditor getEditor() { |
| return fEditor; |
| } |
| |
| final public void runFromEditor(IAction uiProxy) { |
| |
| // this run is called from Editor |
| IJavaScriptElement element= null; |
| try { |
| element= SelectionConverter.getElementAtOffset(fEditor); |
| } catch (JavaScriptModelException e) { |
| // ignored |
| } |
| |
| fSelection= element != null |
| ? new StructuredSelection(element) |
| : StructuredSelection.EMPTY; |
| boolean isEnabled= isEnabled(fSelection); |
| uiProxy.setEnabled(isEnabled); |
| |
| if (!isEnabled) { |
| MessageDialog.openInformation(getShell(), fTitle, fMessage); |
| return; |
| } |
| run(fSelection); |
| } |
| |
| boolean checkEnabled() { |
| IJavaScriptUnit unit= SelectionConverter.getInputAsCompilationUnit(fEditor); |
| IFile file= getFile(unit); |
| return isEnabled(file); |
| } |
| |
| final public void update(IAction uiProxy) { |
| uiProxy.setEnabled(checkEnabled()); |
| } |
| |
| //---- IActionDelegate |
| |
| final public void selectionChanged(IAction uiProxy, ISelection selection) { |
| fSelection= selection; |
| uiProxy.setEnabled(isEnabled(selection)); |
| } |
| |
| final public void run(IAction action) { |
| run(fSelection); |
| } |
| |
| static JavaScriptUnit parsePartialCompilationUnit(IJavaScriptUnit unit) { |
| |
| if (unit == null) { |
| throw new IllegalArgumentException(); |
| } |
| try { |
| ASTParser c= ASTParser.newParser(AST.JLS3); |
| c.setSource(unit); |
| c.setFocalPosition(0); |
| c.setResolveBindings(false); |
| c.setWorkingCopyOwner(null); |
| ASTNode result= c.createAST(null); |
| return (JavaScriptUnit) result; |
| } catch (IllegalStateException e) { |
| // convert ASTParser's complaints into old form |
| throw new IllegalArgumentException(); |
| } |
| } |
| } |