diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index 067292a42d1d..c32e20cfa020 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -1,6 +1,7 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.source.codeStyle; +import com.intellij.application.options.CodeStyle; import com.intellij.codeInsight.ImportFilter; import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl; import com.intellij.lang.ASTNode; @@ -129,8 +130,7 @@ public class ImportHelper{ String ext = StdFileTypes.JAVA.getDefaultExtension(); PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text); - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject()); - codeStyleManager.reformat(dummyFile); + CodeStyle.reformatWithFileContext(dummyFile, file); PsiImportList newImportList = dummyFile.getImportList(); assert newImportList != null : dummyFile.getText(); diff --git a/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings.java b/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings.java new file mode 100644 index 000000000000..308e4ebb02d0 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings.java @@ -0,0 +1,19 @@ +package com.company; + +import static org.junit.platform.commons.util.StringUtils.containsIsoControlCharacter; + +import com.company.subpackage.AnotherClasss; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; + + +public class Main { + + public static void main(String[] args) { + AnotherClasss anotherClasss = new AnotherClasss(); + List strings = new ArrayList<>(); + containsIsoControlCharacter(args[0]); + Class displayName = DisplayName.class; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings_after.java b/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings_after.java new file mode 100644 index 000000000000..308e4ebb02d0 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/PerFileImportSettings_after.java @@ -0,0 +1,19 @@ +package com.company; + +import static org.junit.platform.commons.util.StringUtils.containsIsoControlCharacter; + +import com.company.subpackage.AnotherClasss; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; + + +public class Main { + + public static void main(String[] args) { + AnotherClasss anotherClasss = new AnotherClasss(); + List strings = new ArrayList<>(); + containsIsoControlCharacter(args[0]); + Class displayName = DisplayName.class; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/psi/OptimizeImportsTest.java b/java/java-tests/testSrc/com/intellij/java/psi/OptimizeImportsTest.java index d4f415e824f4..0ff427648674 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/OptimizeImportsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/OptimizeImportsTest.java @@ -16,9 +16,16 @@ package com.intellij.java.psi; import com.intellij.application.options.CodeStyle; +import com.intellij.formatting.MockCodeStyleSettingsModifier; import com.intellij.formatting.fileSet.NamedScopeDescriptor; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.psi.codeStyle.PackageEntry; +import com.intellij.psi.codeStyle.PackageEntryTable; +import com.intellij.psi.codeStyle.modifier.CodeStyleSettingsModifier; +import com.intellij.testFramework.ServiceContainerUtil; public class OptimizeImportsTest extends OptimizeImportsTestCase { private static final String BASE_PATH = PathManagerEx.getTestDataPath() + "/psi/optimizeImports"; @@ -72,6 +79,21 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase { CodeStyle.doWithTemporarySettings(getProject(), temp, () -> doTest()); } + public void testPerFileImportSettings() { + CodeStyle.dropTemporarySettings(getProject()); + MockCodeStyleSettingsModifier modifier = new MockCodeStyleSettingsModifier( + getTestName(false) + ".java", + settings -> { + JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class); + javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable(); + javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY); + javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY); + javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY); + }); + ServiceContainerUtil.registerExtension(ApplicationManager.getApplication(), CodeStyleSettingsModifier.EP_NAME, modifier, getTestRootDisposable()); + doTest(); + } + private void doTest() { doTest(".java"); } diff --git a/platform/lang-api/src/com/intellij/application/options/CodeStyle.java b/platform/lang-api/src/com/intellij/application/options/CodeStyle.java index 1695eaf8dd31..a83e8b4b61c3 100644 --- a/platform/lang-api/src/com/intellij/application/options/CodeStyle.java +++ b/platform/lang-api/src/com/intellij/application/options/CodeStyle.java @@ -321,7 +321,19 @@ public class CodeStyle { return !getSettings(file).getExcludedFiles().contains(file); } - + /** + * Reformat the given {@code fileToReformat} using code style settings for the {@code contextFile}. The method may be + * useful to reformat a fragment of code (temporary file) which eventually will be inserted to the context file. + * + * @param fileToReformat The file to reformat (may be a temporary dummy file). + * @param contextFile The actual (target) file whose settings must be used. + */ + public static void reformatWithFileContext(@NotNull PsiFile fileToReformat, @NotNull PsiFile contextFile) { + final Project project = contextFile.getProject(); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); + CodeStyleSettings realFileSettings = getSettings(contextFile); + doWithTemporarySettings(project, realFileSettings, () -> codeStyleManager.reformat(fileToReformat)); + } } diff --git a/platform/platform-tests/testSrc/com/intellij/formatting/MockCodeStyleSettingsModifier.java b/platform/platform-tests/testSrc/com/intellij/formatting/MockCodeStyleSettingsModifier.java new file mode 100644 index 000000000000..0502a77117d7 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/formatting/MockCodeStyleSettingsModifier.java @@ -0,0 +1,43 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.formatting; + +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.modifier.CodeStyleSettingsModifier; +import com.intellij.psi.codeStyle.modifier.CodeStyleStatusBarUIContributor; +import com.intellij.psi.codeStyle.modifier.TransientCodeStyleSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public class MockCodeStyleSettingsModifier implements CodeStyleSettingsModifier { + private final String myFileName; + private final Consumer mySettingsConsumer; + + public MockCodeStyleSettingsModifier(@NotNull String fileName, @NotNull Consumer consumer) { + myFileName = fileName; + mySettingsConsumer = consumer; + } + + @Override + public boolean modifySettings(@NotNull TransientCodeStyleSettings settings, + @NotNull PsiFile file) { + if (myFileName.equals(file.getName())) { + mySettingsConsumer.accept(settings); + return true; + } + return false; + } + + @Override + public String getName() { + return "Mock Code Style Modifier"; + } + + @Nullable + @Override + public CodeStyleStatusBarUIContributor getStatusBarUiContributor(@NotNull TransientCodeStyleSettings transientSettings) { + return null; + } +}