Skip to content

Commit 01d2ffa

Browse files
plumpyronshapiro
authored andcommitted
Simplify the GoogleJavaFormatCodeStyleManager.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=182998127
1 parent 6d778e4 commit 01d2ffa

File tree

7 files changed

+143
-131
lines changed

7 files changed

+143
-131
lines changed

idea_plugin/src/com/google/googlejavaformat/intellij/BasicGoogleJavaFormatCodeStyleManager.java

Lines changed: 0 additions & 40 deletions
This file was deleted.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2015 Google Inc. All Rights Reserved.
3+
*
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
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
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.
15+
*/
16+
17+
package com.google.googlejavaformat.intellij;
18+
19+
import static com.google.common.base.Preconditions.checkState;
20+
21+
import com.google.common.collect.BoundType;
22+
import com.google.common.collect.ImmutableMap;
23+
import com.google.common.collect.Range;
24+
import com.google.googlejavaformat.java.Formatter;
25+
import com.google.googlejavaformat.java.FormatterException;
26+
import com.intellij.openapi.util.TextRange;
27+
import java.util.Collection;
28+
import java.util.Map;
29+
import java.util.stream.Collectors;
30+
31+
final class FormatterUtil {
32+
33+
private FormatterUtil() {}
34+
35+
static Map<TextRange, String> getReplacements(
36+
Formatter formatter, String text, Collection<TextRange> ranges) {
37+
try {
38+
ImmutableMap.Builder<TextRange, String> replacements = ImmutableMap.builder();
39+
formatter
40+
.getFormatReplacements(text, toRanges(ranges))
41+
.forEach(
42+
replacement ->
43+
replacements.put(
44+
toTextRange(replacement.getReplaceRange()),
45+
replacement.getReplacementString()));
46+
return replacements.build();
47+
} catch (FormatterException e) {
48+
return ImmutableMap.of();
49+
}
50+
}
51+
52+
private static Collection<Range<Integer>> toRanges(Collection<TextRange> textRanges) {
53+
return textRanges
54+
.stream()
55+
.map(textRange -> Range.closedOpen(textRange.getStartOffset(), textRange.getEndOffset()))
56+
.collect(Collectors.toList());
57+
}
58+
59+
private static TextRange toTextRange(Range<Integer> range) {
60+
checkState(
61+
range.lowerBoundType().equals(BoundType.CLOSED)
62+
&& range.upperBoundType().equals(BoundType.OPEN));
63+
return new TextRange(range.lowerEndpoint(), range.upperEndpoint());
64+
}
65+
}

idea_plugin/src/com/google/googlejavaformat/intellij/GoogleJavaFormatCodeStyleManager.java

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,120 +19,136 @@
1919
import static java.util.Comparator.comparing;
2020

2121
import com.google.common.collect.ImmutableList;
22-
import com.google.common.collect.Range;
2322
import com.google.googlejavaformat.java.Formatter;
24-
import com.google.googlejavaformat.java.FormatterException;
25-
import com.google.googlejavaformat.java.Replacement;
23+
import com.google.googlejavaformat.java.JavaFormatterOptions;
24+
import com.google.googlejavaformat.java.JavaFormatterOptions.Style;
2625
import com.intellij.openapi.application.ApplicationManager;
2726
import com.intellij.openapi.command.WriteCommandAction;
2827
import com.intellij.openapi.editor.Document;
2928
import com.intellij.openapi.fileTypes.StdFileTypes;
3029
import com.intellij.openapi.util.TextRange;
3130
import com.intellij.psi.PsiDocumentManager;
31+
import com.intellij.psi.PsiElement;
3232
import com.intellij.psi.PsiFile;
3333
import com.intellij.psi.codeStyle.CodeStyleManager;
3434
import com.intellij.psi.impl.CheckUtil;
3535
import com.intellij.util.IncorrectOperationException;
3636
import java.util.Collection;
37-
import java.util.List;
38-
import java.util.Optional;
39-
import java.util.stream.Collectors;
37+
import java.util.Map;
38+
import java.util.Map.Entry;
39+
import java.util.TreeMap;
4040
import org.jetbrains.annotations.NotNull;
4141

4242
/**
4343
* A {@link CodeStyleManager} implementation which formats .java files with google-java-format.
4444
* Formatting of all other types of files is delegated to IJ's default implementation.
45-
*
46-
* @author bcsf@google.com (Brian Chang)
4745
*/
48-
public abstract class GoogleJavaFormatCodeStyleManager extends CodeStyleManagerDecorator {
46+
class GoogleJavaFormatCodeStyleManager extends CodeStyleManagerDecorator {
4947

5048
public GoogleJavaFormatCodeStyleManager(@NotNull CodeStyleManager original) {
5149
super(original);
5250
}
5351

5452
@Override
55-
public void reformatText(@NotNull PsiFile file, int startOffset, int endOffset)
53+
public void reformatText(PsiFile file, int startOffset, int endOffset)
5654
throws IncorrectOperationException {
57-
Optional<Formatter> formatter = getFormatterForFile(file);
58-
if (formatter.isPresent() && StdFileTypes.JAVA.equals(file.getFileType())) {
59-
formatInternal(
60-
formatter.get(), file, ImmutableList.of(Range.closedOpen(startOffset, endOffset)));
55+
if (overrideFormatterForFile(file)) {
56+
formatInternal(file, ImmutableList.of(new TextRange(startOffset, endOffset)));
6157
} else {
6258
super.reformatText(file, startOffset, endOffset);
6359
}
6460
}
6561

6662
@Override
67-
public void reformatText(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges)
63+
public void reformatText(PsiFile file, Collection<TextRange> ranges)
6864
throws IncorrectOperationException {
69-
Optional<Formatter> formatter = getFormatterForFile(file);
70-
if (formatter.isPresent() && StdFileTypes.JAVA.equals(file.getFileType())) {
71-
formatInternal(formatter.get(), file, convertToRanges(ranges));
65+
if (overrideFormatterForFile(file)) {
66+
formatInternal(file, ranges);
7267
} else {
7368
super.reformatText(file, ranges);
7469
}
7570
}
7671

7772
@Override
78-
public void reformatTextWithContext(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges)
79-
throws IncorrectOperationException {
80-
Optional<Formatter> formatter = getFormatterForFile(file);
81-
if (formatter.isPresent() && StdFileTypes.JAVA.equals(file.getFileType())) {
82-
formatInternal(formatter.get(), file, convertToRanges(ranges));
73+
public void reformatTextWithContext(PsiFile file, Collection<TextRange> ranges) {
74+
if (overrideFormatterForFile(file)) {
75+
formatInternal(file, ranges);
8376
} else {
8477
super.reformatTextWithContext(file, ranges);
8578
}
8679
}
8780

88-
/**
89-
* Get the {@link Formatter} to be used with the given file, or absent to use the built-in
90-
* IntelliJ formatter.
91-
*/
92-
protected abstract Optional<Formatter> getFormatterForFile(PsiFile file);
81+
@Override
82+
public PsiElement reformatRange(
83+
PsiElement element, int startOffset, int endOffset, boolean canChangeWhiteSpacesOnly) {
84+
// Only handle elements that are PsiFile for now -- otherwise we need to search for some
85+
// element within the file at new locations given the original startOffset and endOffsets
86+
// to serve as the return value.
87+
PsiFile file = element instanceof PsiFile ? (PsiFile) element : null;
88+
if (file != null && canChangeWhiteSpacesOnly && overrideFormatterForFile(file)) {
89+
formatInternal(file, ImmutableList.of(new TextRange(startOffset, endOffset)));
90+
return file;
91+
} else {
92+
return super.reformatRange(element, startOffset, endOffset, canChangeWhiteSpacesOnly);
93+
}
94+
}
9395

94-
private void formatInternal(Formatter formatter, PsiFile file, List<Range<Integer>> ranges)
95-
throws IncorrectOperationException {
96+
/** Return whether or not this formatter can handle formatting the given file. */
97+
private boolean overrideFormatterForFile(PsiFile file) {
98+
return StdFileTypes.JAVA.equals(file.getFileType())
99+
&& GoogleJavaFormatSettings.getInstance(getProject()).isEnabled();
100+
}
101+
102+
private void formatInternal(PsiFile file, Collection<TextRange> ranges) {
96103
ApplicationManager.getApplication().assertWriteAccessAllowed();
97-
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
104+
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
105+
documentManager.commitAllDocuments();
98106
CheckUtil.checkWritable(file);
99107

100-
Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
101-
if (document != null) {
102-
try {
103-
List<Replacement> replacements =
104-
formatter
105-
.getFormatReplacements(document.getText(), ranges)
106-
.stream()
107-
.sorted(
108-
comparing((Replacement r) -> r.getReplaceRange().lowerEndpoint()).reversed())
109-
.collect(Collectors.toList());
110-
performReplacements(document, replacements);
111-
} catch (FormatterException e) {
112-
// Do not format on errors
113-
}
108+
Document document = documentManager.getDocument(file);
109+
110+
if (document == null) {
111+
return;
114112
}
113+
// If there are postponed PSI changes (e.g., during a refactoring), just abort.
114+
// If we apply them now, then the incoming text ranges may no longer be valid.
115+
if (documentManager.isDocumentBlockedByPsi(document)) {
116+
return;
117+
}
118+
119+
format(document, ranges);
120+
}
121+
122+
/**
123+
* Format the ranges of the given document.
124+
*
125+
* <p>Overriding methods will need to modify the document with the result of the external
126+
* formatter (usually using {@link #performReplacements(Document, Map)}.
127+
*/
128+
private void format(Document document, Collection<TextRange> ranges) {
129+
Style style = GoogleJavaFormatSettings.getInstance(getProject()).getStyle();
130+
Formatter formatter = new Formatter(JavaFormatterOptions.builder().style(style).build());
131+
performReplacements(
132+
document, FormatterUtil.getReplacements(formatter, document.getText(), ranges));
115133
}
116134

117135
private void performReplacements(
118-
final Document document, final List<Replacement> reverseSortedReplacements) {
136+
final Document document, final Map<TextRange, String> replacements) {
137+
138+
if (replacements.isEmpty()) {
139+
return;
140+
}
141+
142+
TreeMap<TextRange, String> sorted = new TreeMap<>(comparing(TextRange::getStartOffset));
143+
sorted.putAll(replacements);
119144
WriteCommandAction.runWriteCommandAction(
120145
getProject(),
121146
() -> {
122-
for (Replacement replacement : reverseSortedReplacements) {
123-
Range<Integer> range = replacement.getReplaceRange();
147+
for (Entry<TextRange, String> entry : sorted.descendingMap().entrySet()) {
124148
document.replaceString(
125-
range.lowerEndpoint(), range.upperEndpoint(), replacement.getReplacementString());
149+
entry.getKey().getStartOffset(), entry.getKey().getEndOffset(), entry.getValue());
126150
}
127151
PsiDocumentManager.getInstance(getProject()).commitDocument(document);
128152
});
129153
}
130-
131-
private static List<Range<Integer>> convertToRanges(Collection<TextRange> textRanges) {
132-
ImmutableList.Builder<Range<Integer>> ranges = ImmutableList.builder();
133-
for (TextRange textRange : textRanges) {
134-
ranges.add(Range.closedOpen(textRange.getStartOffset(), textRange.getEndOffset()));
135-
}
136-
return ranges.build();
137-
}
138154
}

idea_plugin/src/com/google/googlejavaformat/intellij/GoogleJavaFormatCodeStyleManagerFactory.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

idea_plugin/src/com/google/googlejavaformat/intellij/GoogleJavaFormatInstaller.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,20 @@
2424
* A utility class to replace (and revert) the default IntelliJ {@link CodeStyleManager} with one
2525
* that formats via google-java-format.
2626
*/
27-
public final class GoogleJavaFormatInstaller {
27+
final class GoogleJavaFormatInstaller {
2828

2929
private static final String CODE_STYLE_MANAGER_KEY = CodeStyleManager.class.getName();
3030

3131
private GoogleJavaFormatInstaller() {}
3232

33-
public static void installFormatter(
34-
Project project, GoogleJavaFormatCodeStyleManagerFactory factory) {
33+
public static void installFormatter(Project project) {
3534
CodeStyleManager currentManager = CodeStyleManager.getInstance(project);
3635

3736
if (currentManager instanceof GoogleJavaFormatCodeStyleManager) {
3837
currentManager = ((GoogleJavaFormatCodeStyleManager) currentManager).getDelegate();
3938
}
4039

41-
setManager(project, factory.createFormatter(currentManager));
40+
setManager(project, new GoogleJavaFormatCodeStyleManager(currentManager));
4241
}
4342

4443
public static void removeFormatter(Project project) {

idea_plugin/src/com/google/googlejavaformat/intellij/GoogleJavaFormatSettings.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ void setStyle(JavaFormatterOptions.Style style) {
7474

7575
private void updateFormatterState() {
7676
if (state.enabled) {
77-
GoogleJavaFormatInstaller.installFormatter(
78-
myProject,
79-
(delegate) -> new BasicGoogleJavaFormatCodeStyleManager(delegate, state.style));
77+
GoogleJavaFormatInstaller.installFormatter(myProject);
8078
} else {
8179
GoogleJavaFormatInstaller.removeFormatter(myProject);
8280
}

idea_plugin/src/com/google/googlejavaformat/intellij/UiFormatterStyle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import java.util.Objects;
2323

2424
/** Configuration options for the formatting style. */
25-
public enum UiFormatterStyle {
25+
enum UiFormatterStyle {
2626
GOOGLE("Default Google Java style", Style.GOOGLE),
2727
AOSP("Android Open Source Project (AOSP) style", Style.AOSP);
2828

0 commit comments

Comments
 (0)