blob: a834dbd383b1b292f3f039e1f71b0b62dffe767e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 University of Illinois at Urbana-Champaign 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.ui.actions;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.photran.core.IFortranAST;
import org.eclipse.photran.internal.core.FortranAST;
import org.eclipse.photran.internal.core.SyntaxException;
import org.eclipse.photran.internal.core.lexer.ASTLexerFactory;
import org.eclipse.photran.internal.core.lexer.IAccumulatingLexer;
import org.eclipse.photran.internal.core.lexer.LexerException;
import org.eclipse.photran.internal.core.lexer.TokenList;
import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
import org.eclipse.photran.internal.core.parser.Parser;
import org.eclipse.photran.internal.core.refactoring.infrastructure.SourcePrinter;
import org.eclipse.photran.internal.core.reindenter.Reindenter;
import org.eclipse.photran.internal.core.reindenter.Reindenter.Strategy;
import org.eclipse.photran.internal.core.sourceform.SourceForm;
/**
* The Correct Indentation action in the Fortran editor's context menu.
*
* @author Esfar Huq
* @author Rui Wang
* @author Jeff Overbey
*/
public class CorrectIndentationAction extends FortranEditorASTActionDelegate
{
public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException
{
try
{
if (ensureNotFixedForm())
{
ITextSelection selectedRegion = getFortranEditor().getSelection();
String sourceCode = reindent(selectedRegion);
setTextInEditor(sourceCode);
setEditorSelectionTo(selectedRegion, sourceCode);
}
}
catch (Exception e)
{
String message = e.getMessage();
if (message == null) message = e.getClass().getName();
MessageDialog.openError(getFortranEditor().getShell(), "Error", message); //$NON-NLS-1$
}
}
/** @return true iff the file in the editor has free source form */
private boolean ensureNotFixedForm()
{
IFile ifile = getFortranEditor().getIFile();
if (ifile != null && SourceForm.of(ifile).isFixedForm())
{
MessageDialog.openError(getFortranEditor().getShell(), "Error", //$NON-NLS-1$
Messages.CorrectIndentationAction_NotAvailableForFixedForm);
return false;
}
else return true;
}
private String reindent(ITextSelection selection) throws IOException, LexerException, SyntaxException
{
IFortranAST ast = parseTextInEditor();
if (selection.getLength() == 0)
Reindenter.reindent(ast.getRoot(), ast, Strategy.REINDENT_EACH_LINE);
else
Reindenter.reindent(selection.getStartLine()+1, selection.getEndLine()+1, ast, Strategy.REINDENT_EACH_LINE);
return SourcePrinter.getSourceCodeFromAST(ast);
}
private IFortranAST parseTextInEditor() throws IOException, LexerException, SyntaxException
{
IFile ifile = getFortranEditor().getIFile();
String filename = ifile != null ? ifile.getName() : "new_file.f90"; //$NON-NLS-1$
IAccumulatingLexer lexer = new ASTLexerFactory().createLexer(
new StringReader(getDocument().get()),
ifile,
filename,
SourceForm.of(ifile));
ASTExecutableProgramNode astRoot = new Parser().parse(lexer);
return new FortranAST(ifile, astRoot, new TokenList(astRoot));
}
private IDocument getDocument()
{
return getFortranEditor().getDocumentProvider().getDocument(getFortranEditor().getEditorInput());
}
private void setTextInEditor(String sourceCode)
{
getDocument().set(sourceCode);
}
private void setEditorSelectionTo(ITextSelection selection, String sourceCode)
{
// int newStartOffset = Math.min(selection.getOffset(), sourceCode.length()-1);
// int newEndOffset = Math.min(newStartOffset+selection.getLength(), sourceCode.length()-1);
// getFortranEditor().selectAndReveal(newStartOffset, newEndOffset-newStartOffset);
int newOffset = Math.min(selection.getOffset(), sourceCode.length()-1);
getFortranEditor().selectAndReveal(newOffset, 0);
}
}