File indent options provider API: a flag to skip a provider on full reformat, logging

This commit is contained in:
Rustam Vishnyakov
2014-09-24 11:45:44 +04:00
parent 0c0b29bf42
commit ec603b4814
14 changed files with 156 additions and 21 deletions
@@ -72,7 +72,7 @@ public class TabPostFormatProcessor implements PostFormatProcessor {
if (!source.isValid()) return range;
PsiFile file = source.getContainingFile();
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptionsByFile(file);
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptionsByFile(file, range);
boolean useTabs = indentOptions.USE_TAB_CHARACTER;
boolean smartTabs = indentOptions.SMART_TABS;
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -1,8 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -0,0 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -1,8 +1,8 @@
class A {
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
private void foo(boolean b) {
int x;
if (b) {
System.out.println(x);
}
}
}
@@ -38,6 +38,7 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
private final static FileIndentOptionsProvider TEST_FILE_INDENT_OPTIONS_PROVIDER = new TestIndentOptionsProvider();
private static CommonCodeStyleSettings.IndentOptions myTestIndentOptions;
private static boolean myUseOnFullReformat;
@Override
protected void setUp() throws Exception {
@@ -54,6 +55,7 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
Extensions.getRootArea().getExtensionPoint(FileIndentOptionsProvider.EP_NAME);
extensionPoint.unregisterExtension(TEST_FILE_INDENT_OPTIONS_PROVIDER);
myTestIndentOptions = null;
myUseOnFullReformat = false;
super.tearDown();
}
@@ -80,6 +82,11 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
public CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile file) {
return myTestIndentOptions;
}
@Override
public boolean useOnFullReformat() {
return myUseOnFullReformat;
}
}
public void testTypeEnter() {
@@ -111,6 +118,16 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
public void testReformatFileSupported() {
myUseOnFullReformat = true;
myTestIndentOptions.INDENT_SIZE = 3;
myTestIndentOptions.TAB_SIZE = 2;
myTestIndentOptions.USE_TAB_CHARACTER = true;
PsiFile file = myFixture.configureByFile(getTestName(true) + "_before.java");
CodeStyleManager.getInstance(getProject()).reformat(file);
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
public void testReformatText() {
myTestIndentOptions.INDENT_SIZE = 3;
myTestIndentOptions.TAB_SIZE = 2;
@@ -119,4 +136,27 @@ public class FileIndentProviderTest extends LightPlatformCodeInsightFixtureTestC
CodeStyleManager.getInstance(getProject()).reformatText(file, 0, file.getTextRange().getEndOffset());
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
/**
* Reformat using indent provider if a part of the file is selected.
*/
public void testReformatTextRange() {
myTestIndentOptions.INDENT_SIZE = 3;
myTestIndentOptions.TAB_SIZE = 2;
myTestIndentOptions.USE_TAB_CHARACTER = true;
PsiFile file = myFixture.configureByFile(getTestName(true) + "_before.java");
// Just any range smaller than the file
CodeStyleManager.getInstance(getProject()).reformatText(file, 6, file.getTextRange().getEndOffset() - 1);
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
public void testReformatTextFullSupported() {
myUseOnFullReformat = true;
myTestIndentOptions.INDENT_SIZE = 3;
myTestIndentOptions.TAB_SIZE = 2;
myTestIndentOptions.USE_TAB_CHARACTER = true;
PsiFile file = myFixture.configureByFile(getTestName(true) + "_before.java");
CodeStyleManager.getInstance(getProject()).reformatText(file, 0, file.getTextRange().getEndOffset());
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
}
@@ -663,26 +663,65 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
@NotNull
public IndentOptions getIndentOptionsByFile(@Nullable PsiFile file) {
return getIndentOptionsByFile(file, false);
return getIndentOptionsByFile(file, null);
}
@NotNull
public IndentOptions getIndentOptionsByFile(@Nullable PsiFile file, boolean ignoreDocOptions) {
public IndentOptions getIndentOptionsByFile(@Nullable PsiFile file, @Nullable TextRange formatRange) {
return getIndentOptionsByFile(file, formatRange, false);
}
/**
* Retrieves indent options for PSI file from an associated document or (if not defined in the document) from file indent options
* providers.
* @param file The PSI file to retrieve options for.
* @param formatRange The text range within the file for formatting purposes or null if there is either no specific range or multiple
* ranges. If the range covers the entire file (full reformat), options stored in the document are ignored and
* indent options are taken from file indent options providers.
* @param ignoreDocOptions Ignore options stored in the document and use file indent options providers even if there is no text range
* or the text range doesn't cover the entire file.
* @return Indent options from the associated document or file indent options providers.
* @see com.intellij.psi.codeStyle.FileIndentOptionsProvider
*/
@NotNull
public IndentOptions getIndentOptionsByFile(@Nullable PsiFile file, @Nullable TextRange formatRange, boolean ignoreDocOptions) {
if (file != null && file.isValid()) {
if (!ignoreDocOptions) {
boolean isFullReformat = isFileFullyCoveredByRange(file, formatRange);
if (!ignoreDocOptions && !isFullReformat) {
IndentOptions docOptions = IndentOptions.retrieveFromAssociatedDocument(file);
if (docOptions != null) return docOptions;
}
FileIndentOptionsProvider[] providers = Extensions.getExtensions(FileIndentOptionsProvider.EP_NAME);
for (FileIndentOptionsProvider provider : providers) {
IndentOptions indentOptions = provider.getIndentOptions(file);
if (indentOptions != null) return indentOptions;
if (!isFullReformat || provider.useOnFullReformat()) {
IndentOptions indentOptions = provider.getIndentOptions(file);
if (indentOptions != null) {
logIndentOptions(file, provider, indentOptions);
return indentOptions;
}
}
}
return getIndentOptions(file.getFileType());
}
else
return OTHER_INDENT_OPTIONS;
}
private static boolean isFileFullyCoveredByRange(@NotNull PsiFile file, @Nullable TextRange formatRange) {
return
formatRange != null &&
file.getTextRange().equals(formatRange);
}
private static void logIndentOptions(@NotNull PsiFile file,
@NotNull FileIndentOptionsProvider provider,
@NotNull IndentOptions options) {
LOG.info("Indent options returned by " + provider.getClass().getName() +
" for " + file.getName() +
": indent size=" + options.INDENT_SIZE +
", use tabs=" + options.USE_TAB_CHARACTER +
", tab size=" + options.TAB_SIZE);
}
@Nullable
private IndentOptions getLanguageIndentOptions(@Nullable FileType fileType) {
@@ -139,7 +139,7 @@ public class CodeStyleSettingsManager implements PersistentStateComponent<Elemen
if (documentManager != null) {
PsiFile file = documentManager.getPsiFile(document);
if (file != null) {
CommonCodeStyleSettings.IndentOptions indentOptions = getSettings(project).getIndentOptionsByFile(file, true);
CommonCodeStyleSettings.IndentOptions indentOptions = getSettings(project).getIndentOptionsByFile(file, null, true);
indentOptions.associateWithDocument(document);
}
}
@@ -33,4 +33,12 @@ public abstract class FileIndentOptionsProvider {
*/
@Nullable
public abstract CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile file);
/**
* Tells if the provider can be used when a complete file is reformatted.
* @return True by default
*/
public boolean useOnFullReformat() {
return true;
}
}
@@ -129,7 +129,7 @@ public class CodeFormatterFacade {
if (file.getTextLength() > 0) {
try {
FormatterEx.getInstanceEx().format(
model, mySettings,mySettings.getIndentOptionsByFile(fileToFormat), new FormatTextRanges(range, true)
model, mySettings,mySettings.getIndentOptionsByFile(fileToFormat, range), new FormatTextRanges(range, true)
);
wrapLongLinesIfNecessary(file, document, startOffset, endOffset);
@@ -242,7 +242,7 @@ public class CodeFormatterFacade {
indentOptions = ((FormattingModelBuilderEx)builder).getIndentOptionsToUse(file, ranges, mySettings);
}
if (indentOptions == null) {
indentOptions = mySettings.getIndentOptionsByFile(file);
indentOptions = mySettings.getIndentOptionsByFile(file, textRanges.size() == 1 ? textRanges.get(0).getTextRange() : null);
}
formatter.format(model, mySettings, indentOptions, ranges);