diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/main/java/pkg/ClassWithDirectoryReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/main/java/pkg/ClassWithDirectoryReference.java new file mode 100644 index 000000000000..6cfef9831e1b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/main/java/pkg/ClassWithDirectoryReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class ClassWithDirectoryReference { + public static void main(String[] args) { + String filePath = "/long/srcdir/path/my.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/test/java/pkg/TestClassWithDirectoryReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/test/java/pkg/TestClassWithDirectoryReference.java new file mode 100644 index 000000000000..ff85d151fca5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath/src/test/java/pkg/TestClassWithDirectoryReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class TestClassWithDirectoryReference { + public static void main(String[] args) { + String filePath = "/long/testdir/path/my-test.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithFileReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithFileReference.java new file mode 100644 index 000000000000..ea28dea5b138 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithFileReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class ClassWithFileReference { + public static void main(String[] args) { + String filePath = "/pkg/my.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithLongFileReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithLongFileReference.java new file mode 100644 index 000000000000..55982eae80a2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/java/pkg/ClassWithLongFileReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class ClassWithLongFileReference { + public static void main(String[] args) { + String filePath = "/long/path/source/my.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/resources/.keep b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/main/resources/.keep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithFileReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithFileReference.java new file mode 100644 index 000000000000..ca4c61941dff --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithFileReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class TestClassWithFileReference { + public static void main(String[] args) { + String filePath = "/pkg/my-test.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithLongFileReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithLongFileReference.java new file mode 100644 index 000000000000..7f8a5289ee51 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/java/pkg/TestClassWithLongFileReference.java @@ -0,0 +1,7 @@ +package pkg; + +public class TestClassWithLongFileReference { + public static void main(String[] args) { + String filePath = "/long/path/source/my-test.properties"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/resources/.keep b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath/src/test/resources/.keep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateDirectoryPathFixTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateDirectoryPathFixTest.kt new file mode 100644 index 000000000000..fd59531379c9 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateDirectoryPathFixTest.kt @@ -0,0 +1,45 @@ +// 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.codeInsight.daemon.quickFix + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference +import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference + +class CreateDirectoryPathFixTest : CreateFileQuickFixTestCase() { + + override fun setUp() { + super.setUp() + + myFixture.copyDirectoryToProject("src", "") + } + + override fun getTestCasePath(): String { + return "/codeInsight/daemonCodeAnalyzer/quickFix/createDirectoryPath" + } + + fun testCreateSourceDirectory() { + assertIntentionCreatesDir("srcdir", "/main/java/long/srcdir", "/main/java/pkg/ClassWithDirectoryReference.java") + } + + fun testCreateTestDirectory() { + assertIntentionCreatesDir("testdir", "/test/java/long/testdir", "/test/java/pkg/TestClassWithDirectoryReference.java") + } + + private fun assertIntentionCreatesDir(expectedDirName: String, expectedDirPath: String, javaSourcePath: String) { + myFixture.configureFromTempProjectFile(javaSourcePath) + myFixture.testHighlighting(true, false, true) + + withFileReferenceInStringLiteral { + val ref = myFixture.getReferenceAtCaretPosition() + val fileReference = (ref as PsiMultiReference).references.filterIsInstance()[0] + + assertEquals(expectedDirName, fileReference.fileNameToCreate) + val intention = fileReference.quickFixes!![0] + + myFixture.launchAction(intention as IntentionAction) + + val notFoundDirectory = myFixture.findFileInTempDir(expectedDirPath) + assertTrue(notFoundDirectory.exists()) + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFilePathFixTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFilePathFixTest.kt new file mode 100644 index 000000000000..10a3c97b5dbb --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFilePathFixTest.kt @@ -0,0 +1,94 @@ +// 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.codeInsight.daemon.quickFix + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.application.ApplicationManager +import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference +import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference + +class CreateFilePathFixTest : CreateFileQuickFixTestCase() { + + override fun setUp() { + super.setUp() + + myFixture.copyDirectoryToProject("src", "") + } + + override fun getTestCasePath(): String { + return "/codeInsight/daemonCodeAnalyzer/quickFix/createFilePath" + } + + fun testCreatePathWithSingleSourceRoot() { + ApplicationManager.getApplication().runWriteAction { + // only src/main/java will be available for new files + myFixture.tempDirFixture.getFile("/main/resources")!!.delete(null) + myFixture.tempDirFixture.getFile("/test/resources")!!.delete(null) + myFixture.tempDirFixture.getFile("/test/java")!!.delete(null) + } + + assertIntentionCreatesFile("my.properties", "/main/java/pkg/my.properties", + "/main/java/pkg/ClassWithFileReference.java") + } + + fun testCreatePathInSources() { + ApplicationManager.getApplication().runWriteAction { + // only src/main/java and /src/test/java will be available for new files + myFixture.tempDirFixture.getFile("/main/resources")!!.delete(null) + myFixture.tempDirFixture.getFile("/test/resources")!!.delete(null) + } + + assertIntentionCreatesFile("my.properties", "/main/java/pkg/my.properties", + "/main/java/pkg/ClassWithFileReference.java") + } + + fun testCreatePathInResources() { + assertIntentionCreatesFile("my.properties", "/main/resources/pkg/my.properties", + "/main/java/pkg/ClassWithFileReference.java") + } + + fun testCreatePathInTestResources() { + assertIntentionCreatesFile("my-test.properties", "/test/resources/pkg/my-test.properties", + "/test/java/pkg/TestClassWithFileReference.java") + } + + fun testCreatePathInTestSources() { + ApplicationManager.getApplication().runWriteAction { + // only src/test/java and src/main/java will be available for new files + myFixture.tempDirFixture.getFile("/main/resources")!!.delete(null) + myFixture.tempDirFixture.getFile("/test/resources")!!.delete(null) + } + + assertIntentionCreatesFile("my-test.properties", "/test/java/pkg/my-test.properties", + "/test/java/pkg/TestClassWithFileReference.java") + } + + fun testCreateIntermediateSourcePathAutomatically() { + assertIntentionCreatesFile("my.properties", "/main/resources/long/path/source/my.properties", + "/main/java/pkg/ClassWithLongFileReference.java") + } + + fun testCreateIntermediateTestPathAutomatically() { + assertIntentionCreatesFile("my-test.properties", "/test/resources/long/path/source/my-test.properties", + "/test/java/pkg/TestClassWithLongFileReference.java") + } + + private fun assertIntentionCreatesFile(expectedFileName: String, expectedFilePath: String, javaSourcePath: String) { + myFixture.configureFromTempProjectFile(javaSourcePath) + myFixture.testHighlighting(true, false, true) + + withFileReferenceInStringLiteral { + val ref = myFixture.getReferenceAtCaretPosition() + val fileReference = (ref as PsiMultiReference).references.filterIsInstance()[0] + + assertEquals(expectedFileName, fileReference.fileNameToCreate) + val intention = fileReference.quickFixes!![0] + + myFixture.launchAction(intention as IntentionAction) + + val notFoundFile = myFixture.configureFromTempProjectFile(expectedFilePath) + assertNotNull(notFoundFile) + + myFixture.checkResult("", true) + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFileQuickFixTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFileQuickFixTestCase.java new file mode 100644 index 000000000000..e9dc2f73c4f8 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFileQuickFixTestCase.java @@ -0,0 +1,75 @@ +// 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.codeInsight.daemon.quickFix; + +import com.intellij.JavaTestUtil; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.patterns.PlatformPatterns; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.PsiLiteralExpression; +import com.intellij.psi.PsiReferenceProvider; +import com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.java.JavaResourceRootType; +import org.jetbrains.jps.model.java.JavaSourceRootType; + +public abstract class CreateFileQuickFixTestCase extends LightJavaCodeInsightFixtureTestCase { + + protected static class StandardContentRootsProjectDescriptor extends ProjectDescriptor { + + public StandardContentRootsProjectDescriptor() { + super(LanguageLevel.HIGHEST); + } + + @Override + public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { + super.configureModule(module, model, contentEntry); + + contentEntry.clearSourceFolders(); + + String contentEntryUrl = contentEntry.getUrl(); + + contentEntry.addSourceFolder(contentEntryUrl + "/main/java", JavaSourceRootType.SOURCE); + contentEntry.addSourceFolder(contentEntryUrl + "/main/resources", JavaResourceRootType.RESOURCE); + + contentEntry.addSourceFolder(contentEntryUrl + "/test/java", JavaSourceRootType.TEST_SOURCE); + contentEntry.addSourceFolder(contentEntryUrl + "/test/resources", JavaResourceRootType.TEST_RESOURCE); + } + } + + public static final StandardContentRootsProjectDescriptor STANDARD_CONTENT_ROOTS_DESCRIPTOR = new StandardContentRootsProjectDescriptor(); + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return STANDARD_CONTENT_ROOTS_DESCRIPTOR; + } + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + getTestCasePath(); + } + + protected abstract String getTestCasePath(); + + protected void withFileReferenceInStringLiteral(Runnable action) { + PsiReferenceRegistrarImpl referenceProvidersRegistry = + (PsiReferenceRegistrarImpl)ReferenceProvidersRegistry.getInstance().getRegistrar(JavaLanguage.INSTANCE); + PsiReferenceProvider fileReferenceProvider = new FilePathReferenceProvider(); + + try { + referenceProvidersRegistry.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression.class), fileReferenceProvider); + getPsiManager().dropPsiCaches(); + action.run(); + } + finally { + referenceProvidersRegistry.unregisterReferenceProvider(PsiLiteralExpression.class, fileReferenceProvider); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/AbstractCreateFileFix.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/AbstractCreateFileFix.java index 7075244c6970..fbf895114c94 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/AbstractCreateFileFix.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/AbstractCreateFileFix.java @@ -92,7 +92,7 @@ public abstract class AbstractCreateFileFix extends LocalQuickFixAndIntentionAct return; } - if (editor == null) { + if (editor == null || ApplicationManager.getApplication().isUnitTestMode()) { // run on first item of sorted list in batch mode apply(myStartElement.getProject(), directories.get(0)); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiFileReferenceHelper.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiFileReferenceHelper.java index b69bb0c39f55..07b81a5e48af 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiFileReferenceHelper.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiFileReferenceHelper.java @@ -163,8 +163,11 @@ public class PsiFileReferenceHelper extends FileReferenceHelper { List targetContextWrappers = findSourceRootTypes(targetContexts); - // sort only if we have resource roots - if (ContainerUtil.find(targetContextWrappers, PsiFileReferenceHelper::isResourceRoot) == null) { + // sort only if we different source root types + if (targetContextWrappers.stream() + .map(FileTargetContextWrapper::getSourceRootType) + .distinct() + .count() < 2) { return targetContexts; }