2 * Copyright 2000-2013 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight.actions;
18 import com.intellij.openapi.command.CommandProcessor;
19 import com.intellij.openapi.components.ServiceManager;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.editor.SelectionModel;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.util.TextRange;
25 import com.intellij.psi.PsiDocumentManager;
26 import com.intellij.psi.PsiFile;
27 import com.intellij.psi.codeStyle.arrangement.Rearranger;
28 import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
29 import com.intellij.util.containers.ContainerUtil;
30 import com.intellij.util.diff.FilesTooBigForDiffException;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
34 import java.util.Collection;
35 import java.util.concurrent.Callable;
36 import java.util.concurrent.FutureTask;
38 public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor {
40 public static final String COMMAND_NAME = "Rearrange code";
41 public static final String PROGRESS_TEXT = "Rearranging code...";
43 private static final Logger LOG = Logger.getInstance(RearrangeCodeProcessor.class);
44 private SelectionModel mySelectionModel;
46 public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) {
47 super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
50 public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel model) {
51 super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
52 mySelectionModel = model;
55 public RearrangeCodeProcessor(@NotNull PsiFile file,
56 @NotNull SelectionModel selectionModel)
58 super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false);
59 mySelectionModel = selectionModel;
62 public RearrangeCodeProcessor(@NotNull PsiFile file) {
63 super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false);
66 public RearrangeCodeProcessor(@NotNull Project project,
67 @NotNull PsiFile[] files,
68 @NotNull String commandName,
69 @Nullable Runnable postRunnable) {
70 super(project, files, PROGRESS_TEXT, commandName, postRunnable, false);
75 protected FutureTask<Boolean> prepareTask(@NotNull final PsiFile file, final boolean processChangedTextOnly) {
76 return new FutureTask<Boolean>(new Callable<Boolean>() {
78 public Boolean call() throws Exception {
80 Collection<TextRange> ranges = getRangesToFormat(file, processChangedTextOnly);
81 RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges);
82 if (rearranger.couldRearrange()) {
87 catch (FilesTooBigForDiffException e) {
88 handleFileTooBigException(LOG, e, file);
95 public Collection<TextRange> getRangesToFormat(@NotNull PsiFile file, boolean processChangedTextOnly) throws FilesTooBigForDiffException {
96 if (mySelectionModel != null) {
97 return getSelectedRanges(mySelectionModel);
100 if (processChangedTextOnly) {
101 return FormatChangedTextUtil.getChangedTextRanges(myProject, file);
104 return ContainerUtil.newSmartList(file.getTextRange());
109 class RearrangeCommand {
110 @NotNull private PsiFile myFile;
111 @NotNull private String myCommandName;
112 @NotNull private Project myProject;
113 private Document myDocument;
114 private Runnable myCommand;
115 private final Collection<TextRange> myRanges;
117 RearrangeCommand(@NotNull Project project, @NotNull PsiFile file, @NotNull String commandName, @NotNull Collection<TextRange> ranges) {
121 myCommandName = commandName;
122 myDocument = PsiDocumentManager.getInstance(project).getDocument(file);
125 boolean couldRearrange() {
126 return myDocument != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null;
130 assert myDocument != null;
133 CommandProcessor.getInstance().executeCommand(myProject, myCommand, myCommandName, null);
136 PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
140 private void prepare() {
141 final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class);
142 myCommand = new Runnable() {
145 engine.arrange(myFile, myRanges);
148 PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument);