Detectable indent options provider implementation

This commit is contained in:
Rustam Vishnyakov
2014-09-25 12:03:20 +04:00
parent 44fbcc7197
commit cae66e0fb3
16 changed files with 242 additions and 12 deletions
@@ -0,0 +1,9 @@
public class Main {
public void main() {
try {
System.out.println();<caret>
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
@@ -0,0 +1,10 @@
public class Main {
public void main() {
try {
System.out.println();
<caret>
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
@@ -0,0 +1,9 @@
public class Main {
public void main() {
try {
System.out.println();<caret>
} catch (java.lang.Exception exception) {
exception.printStackTrace();
}
}
}
@@ -0,0 +1,10 @@
public class Main {
public void main() {
try {
System.out.println();
<caret>
} catch (java.lang.Exception exception) {
exception.printStackTrace();
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions;
import com.intellij.psi.codeStyle.autodetect.DetectableIndentOptionsProvider;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.LightCodeInsightTestCase;
/**
* @author Rustam Vishnyakov
*/
public class JavaDetectableIndentsTest extends LightCodeInsightTestCase {
private static final String BASE_PATH = "/codeInsight/editorActions/detectableIndents/";
public void testSpaceIndent() {
doTest();
}
public void testTabIndent() {
doTest();
}
private void doTest() {
DetectableIndentOptionsProvider provider = DetectableIndentOptionsProvider.getInstance();
assertNotNull("DetectableIndentOptionsProvider not found", provider);
String testName = getTestName(true);
provider.setEnabledInTest(true);
try {
configureByFile(BASE_PATH + testName + ".java");
EditorTestUtil.performTypingAction(getEditor(), '\n');
checkResultByFile(BASE_PATH + testName + "_after.java");
}
finally {
provider.setEnabledInTest(false);
}
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.FileIndentOptionsProvider;
import com.intellij.testFramework.PlatformTestUtil;
@@ -79,7 +80,7 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
private static class TestIndentOptionsProvider extends FileIndentOptionsProvider {
@Nullable
@Override
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile file) {
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull CodeStyleSettings settings, @NotNull PsiFile file) {
return myTestIndentOptions;
}
@@ -31,6 +31,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.*;
import com.intellij.psi.codeStyle.autodetect.DetectableIndentOptionsProvider;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.text.LineReader;
@@ -135,6 +136,18 @@ public abstract class AbstractJavaFormatterTest extends LightIdeaTestCase {
doTextTest(Action.REFORMAT, loadFile(fileNameBefore), loadFile(fileNameAfter));
}
public void doTestWithDetectableIndentOptions(@NonNls String text, @NonNls String textAfter) {
DetectableIndentOptionsProvider provider = DetectableIndentOptionsProvider.getInstance();
assertNotNull("DetectableIndentOptionsProvider not found", provider);
provider.setEnabledInTest(true);
try {
doTextTest(text, textAfter);
}
finally {
provider.setEnabledInTest(false);
}
}
public void doTextTest(@NonNls final String text, @NonNls String textAfter) throws IncorrectOperationException {
doTextTest(Action.REFORMAT, text, textAfter);
}
@@ -3049,4 +3049,44 @@ public void testSCR260() throws Exception {
"}"
);
}
public void testDetectableIndentOptions() {
final String original =
"public class Main {\n" +
"\tpublic void main() {\n" +
"try {\n" +
"\t\t\tSystem.out.println();\n" +
"\t} catch (java.lang.Exception exception) {\n" +
"\t\t\texception.printStackTrace();\n" +
"\t}\n" +
"}\n" +
"}";
// Enabled but full reformat (no detection)
doTestWithDetectableIndentOptions(
original,
"public class Main {\n" +
" public void main() {\n" +
" try {\n" +
" System.out.println();\n" +
" } catch (java.lang.Exception exception) {\n" +
" exception.printStackTrace();\n" +
" }\n" +
" }\n" +
"}"
);
// Reformat with a smaller text range (detection is on)
myTextRange = new TextRange(1, original.length());
doTestWithDetectableIndentOptions(
original,
"public class Main {\n" +
"\tpublic void main() {\n" +
"\t\ttry {\n" +
"\t\t\tSystem.out.println();\n" +
"\t\t} catch (java.lang.Exception exception) {\n" +
"\t\t\texception.printStackTrace();\n" +
"\t\t}\n" +
"\t}\n" +
"}"
);
}
}
@@ -166,6 +166,8 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public boolean IGNORE_SAME_INDENTS_FOR_LANGUAGES = false;
public boolean AUTODETECT_INDENTS = true;
@Deprecated
public final IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions();
@Deprecated
@@ -694,7 +696,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
FileIndentOptionsProvider[] providers = Extensions.getExtensions(FileIndentOptionsProvider.EP_NAME);
for (FileIndentOptionsProvider provider : providers) {
if (!isFullReformat || provider.useOnFullReformat()) {
IndentOptions indentOptions = provider.getIndentOptions(file);
IndentOptions indentOptions = provider.getIndentOptions(this, file);
if (indentOptions != null) {
logIndentOptions(file, provider, indentOptions);
return indentOptions;
@@ -28,11 +28,12 @@ public abstract class FileIndentOptionsProvider {
public final static ExtensionPointName<FileIndentOptionsProvider> EP_NAME = ExtensionPointName.create("com.intellij.fileIndentOptionsProvider");
/**
* Retrieves indent options for PSI file.
* @param settings Code style settings for which indent options are calculated.
* @param file The file to retrieve options for.
* @return Indent options or <code>null</code> if the provider can't retrieve them.
*/
@Nullable
public abstract CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile file);
public abstract CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull CodeStyleSettings settings, @NotNull PsiFile file);
/**
* Tells if the provider can be used when a complete file is reformatted.
@@ -7,7 +7,7 @@
<properties/>
<border type="none"/>
<children>
<grid id="6a116" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="6a116" layout-manager="GridLayoutManager" row-count="8" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints border-constraint="West"/>
<properties/>
@@ -57,7 +57,7 @@
</component>
<vspacer id="f290d">
<constraints>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="2586a" binding="myDefaultIndentOptionsPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
@@ -74,7 +74,7 @@
<grid id="f6e61" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
@@ -158,12 +158,20 @@
</grid>
<grid id="5c88a" binding="myAdditionalSettingsPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="253fc" class="javax.swing.JCheckBox" binding="myAutodetectIndentsBox">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/ApplicationBundle" key="settings.code.style.general.autodetect.indents"/>
</properties>
</component>
</children>
</grid>
<hspacer id="b7fa6">
@@ -40,8 +40,6 @@ import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -77,6 +75,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
private JBLabel myFormatterOnLabel;
private JPanel myMarkerOptionsPanel;
private JPanel myAdditionalSettingsPanel;
private JCheckBox myAutodetectIndentsBox;
private final SmartIndentOptionsEditor myIndentOptionsEditor;
private final JBScrollPane myScrollPane;
@@ -160,6 +159,8 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
settings.FORMATTER_ON_TAG = getTagText(myFormatterOnTagField, settings.FORMATTER_ON_TAG);
settings.setFormatterOnPattern(compilePattern(settings, myFormatterOnTagField, settings.FORMATTER_ON_TAG));
settings.AUTODETECT_INDENTS = myAutodetectIndentsBox.isSelected();
for (GeneralCodeStyleOptionsProvider option : myAdditionalOptions) {
option.apply(settings);
}
@@ -229,6 +230,8 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
if (option.isModified(settings)) return true;
}
if (settings.AUTODETECT_INDENTS != myAutodetectIndentsBox.isSelected()) return true;
return myIndentOptionsEditor.isModified(settings, settings.OTHER_INDENT_OPTIONS);
}
@@ -267,6 +270,8 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
setFormatterTagControlsEnabled(settings.FORMATTER_TAGS_ENABLED);
myAutodetectIndentsBox.setSelected(settings.AUTODETECT_INDENTS);
for (GeneralCodeStyleOptionsProvider option : myAdditionalOptions) {
option.reset(settings);
}
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.autodetect;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.FileIndentOptionsProvider;
import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
/**
* @author Rustam Vishnyakov
*/
public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider {
private boolean myIsEnabledInTest;
@Nullable
@Override
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull CodeStyleSettings settings, @NotNull PsiFile file) {
return isEnabled(settings, file) ? new IndentOptionsDetectorImpl(file).getIndentOptions() : null;
}
@Override
public boolean useOnFullReformat() {
return false;
}
@TestOnly
public void setEnabledInTest(boolean isEnabledInTest) {
myIsEnabledInTest = isEnabledInTest;
}
private boolean isEnabled(@NotNull CodeStyleSettings settings, @NotNull PsiFile file) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return myIsEnabledInTest;
}
VirtualFile vFile = file.getVirtualFile();
if (vFile == null || vFile instanceof LightVirtualFile) return false;
return settings.AUTODETECT_INDENTS;
}
@TestOnly
@Nullable
public static DetectableIndentOptionsProvider getInstance() {
FileIndentOptionsProvider[] providers = Extensions.getExtensions(FileIndentOptionsProvider.EP_NAME);
for (FileIndentOptionsProvider provider : providers) {
if (provider instanceof DetectableIndentOptionsProvider) return (DetectableIndentOptionsProvider)provider;
}
return null;
}
}
@@ -644,6 +644,7 @@ settings.code.style.general.formatter.marker.regexp=Regular expressions
settings.code.style.general.formatter.marker.invalid.regexp=Invalid regular expression
settings.code.style.general.formatter.marker.title=Markers
settings.code.style.general.formatter.marker.options.title=Options
settings.code.style.general.autodetect.indents=Detect and use existing file indents for editing
import.scheme.chooser.source=From\:
import.scheme.chooser.destination=To\:
checkbox.reformat.on.typing.rbrace=Reformat block on typing '}'
@@ -895,6 +895,8 @@
<previewPanelProvider implementation="com.intellij.codeInsight.documentation.DocumentationPreviewPanelProvider"/>
<projectService serviceInterface="com.intellij.openapi.preview.PreviewManager"
serviceImplementation="com.intellij.openapi.preview.impl.PreviewManagerImpl"/>
<fileIndentOptionsProvider implementation="com.intellij.psi.codeStyle.autodetect.DetectableIndentOptionsProvider" order="last"/>
</extensions>
</idea-plugin>
@@ -27,13 +27,12 @@ public class EditorConfigIndentOptionsProvider extends FileIndentOptionsProvider
@Nullable
@Override
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile psiFile) {
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull CodeStyleSettings settings, @NotNull PsiFile psiFile) {
final VirtualFile file = psiFile.getVirtualFile();
if (file == null || !file.isInLocalFileSystem()) return null;
final Project project = psiFile.getProject();
final CodeStyleSettings currentSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
if (!Utils.isEnabled(currentSettings)) return null;
if (!Utils.isEnabled(settings)) return null;
// Get editorconfig settings
final String filePath = file.getCanonicalPath();