mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] bring default imports processing into import contributor extension
This commit is contained in:
+2
-1
@@ -53,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFileStub;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrPackageDefinitionStub;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ImplicitImportsKt;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.PackageSkippingProcessor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -165,7 +166,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile {
|
||||
if (!processImports(processor, state, lastParent, place, importStatements, ImportKind.SIMPLE, null)) return false;
|
||||
if (!processDeclarationsInPackage(processor, state, lastParent, place)) return false;
|
||||
if (!processImports(processor, state, lastParent, place, importStatements, ImportKind.ON_DEMAND, null)) return false;
|
||||
if (!GroovyImportHelper.processImplicitImports(processor, state, lastParent, place, this)) return false;
|
||||
if (!ImplicitImportsKt.processImplicitImports(processor, state, lastParent, place, this)) return false;
|
||||
|
||||
if (ResolveUtil.shouldProcessPackages(classHint)) {
|
||||
|
||||
|
||||
+5
-42
@@ -15,13 +15,10 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,11 +26,9 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.GrImportContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.PackageSkippingProcessor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ImportType;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
@@ -75,7 +70,7 @@ public class GroovyImportHelper {
|
||||
for (GrImportContributor contributor : GrImportContributor.EP_NAME.getExtensions()) {
|
||||
result.addAll(ContainerUtil.mapNotNull(
|
||||
contributor.getImports(file),
|
||||
i -> i.getStar() && !i.getStatic() ? i.getName() : null
|
||||
i -> i.getType() == ImportType.STAR ? i.getName() : null
|
||||
));
|
||||
}
|
||||
|
||||
@@ -98,38 +93,6 @@ public class GroovyImportHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processImplicitImports(@NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
@Nullable PsiElement lastParent,
|
||||
@NotNull PsiElement place,
|
||||
@NotNull GroovyFile file) {
|
||||
if (!ResolveUtil.shouldProcessClasses(processor.getHint(ElementClassHint.KEY))) return true;
|
||||
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(file.getProject());
|
||||
|
||||
final PsiScopeProcessor packageSkipper = new PackageSkippingProcessor(processor);
|
||||
|
||||
for (final String implicitlyImported : getImplicitlyImportedPackages(file)) {
|
||||
PsiPackage aPackage = facade.findPackage(implicitlyImported);
|
||||
if (aPackage == null) continue;
|
||||
|
||||
if (!aPackage.processDeclarations(packageSkipper, state, lastParent, place)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
List<PsiClass> implicitlyImportedClasses = CachedValuesManager.getCachedValue(file, () -> {
|
||||
GlobalSearchScope scope = file.getResolveScope();
|
||||
List<PsiClass> classes = ContainerUtil.mapNotNull(GroovyFileBase.IMPLICITLY_IMPORTED_CLASSES, s -> facade.findClass(s, scope));
|
||||
return CachedValueProvider.Result.create(classes, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
|
||||
});
|
||||
|
||||
for (PsiClass clazz : implicitlyImportedClasses) {
|
||||
if (!ResolveUtil.processElement(processor, clazz, state)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ImportKind getImportKind(GrImportStatement statement) {
|
||||
if (statement.isOnDemand() && !statement.isAliasedImport()) return ImportKind.ON_DEMAND;
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyLanguage;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyImportHelper;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ImplicitImportsKt;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.List;
|
||||
@@ -96,7 +96,7 @@ class FromStringLightElement extends LightElement {
|
||||
}
|
||||
}
|
||||
|
||||
if (!GroovyImportHelper.processImplicitImports(processor, state, lastParent, place, myFile)) {
|
||||
if (!ImplicitImportsKt.processImplicitImports(processor, state, lastParent, place, myFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+15
-17
@@ -17,25 +17,23 @@ package org.jetbrains.plugins.groovy.lang.resolve
|
||||
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
|
||||
/**
|
||||
* regular: class
|
||||
* static: class member
|
||||
* star: classes in package
|
||||
* static star: members of class
|
||||
*/
|
||||
class Import(
|
||||
val name: String,
|
||||
val static: Boolean = false,
|
||||
val star: Boolean = false
|
||||
private val classes = listOf(
|
||||
Import("java.math.BigInteger"),
|
||||
Import("java.math.BigDecimal")
|
||||
)
|
||||
|
||||
abstract class GrImportContributorBase : GrImportContributor {
|
||||
private val packages = listOf(
|
||||
Import("java.lang", ImportType.STAR),
|
||||
Import("java.util", ImportType.STAR),
|
||||
Import("java.io", ImportType.STAR),
|
||||
Import("java.net", ImportType.STAR),
|
||||
Import("groovy.lang", ImportType.STAR),
|
||||
Import("groovy.util", ImportType.STAR)
|
||||
)
|
||||
|
||||
abstract fun appendImplicitlyImportedPackages(file: GroovyFile): List<String>
|
||||
private val imports = classes + packages
|
||||
|
||||
final override fun getImports(file: GroovyFile): Collection<Import> {
|
||||
return appendImplicitlyImportedPackages(file).map {
|
||||
Import(name = it, star = true)
|
||||
}
|
||||
}
|
||||
class DefaultImportContributor : GrImportContributor {
|
||||
|
||||
override fun getImports(file: GroovyFile): Collection<Import> = imports
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 org.jetbrains.plugins.groovy.lang.resolve
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.ResolveState
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
|
||||
open class Import(
|
||||
val name: String,
|
||||
val type: ImportType = ImportType.REGULAR
|
||||
)
|
||||
|
||||
enum class ImportType {
|
||||
/**
|
||||
* Class
|
||||
*/
|
||||
REGULAR,
|
||||
/**
|
||||
* Class member
|
||||
*/
|
||||
STATIC,
|
||||
/**
|
||||
* Classes of package
|
||||
*/
|
||||
STAR,
|
||||
/**
|
||||
* Members of class
|
||||
*/
|
||||
STATIC_STAR
|
||||
}
|
||||
|
||||
abstract class GrImportContributorBase : GrImportContributor {
|
||||
|
||||
abstract fun appendImplicitlyImportedPackages(file: GroovyFile): List<String>
|
||||
|
||||
final override fun getImports(file: GroovyFile): Collection<Import> {
|
||||
return appendImplicitlyImportedPackages(file).map {
|
||||
Import(it, ImportType.STAR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getImplicitImports(file: GroovyFile): Collection<Import> = GrImportContributor.EP_NAME.extensions.fold(emptyList()) { acc, ext ->
|
||||
acc + ext.getImports(file)
|
||||
}
|
||||
|
||||
fun processImplicitImports(processor: PsiScopeProcessor,
|
||||
state: ResolveState,
|
||||
lastParent: PsiElement?,
|
||||
place: PsiElement,
|
||||
file: GroovyFile): Boolean {
|
||||
val hint = processor.getHint(com.intellij.psi.scope.ElementClassHint.KEY)
|
||||
val facade = JavaPsiFacade.getInstance(file.project)
|
||||
val packageSkipper = PackageSkippingProcessor(processor)
|
||||
|
||||
loop@for (implicitImport in getImplicitImports(file)) {
|
||||
when (implicitImport.type) {
|
||||
ImportType.REGULAR -> {
|
||||
if (!ResolveUtil.shouldProcessClasses(hint)) continue@loop
|
||||
val clazz = facade.findClass(implicitImport.name, file.resolveScope) ?: continue@loop
|
||||
if (!ResolveUtil.processElement(processor, clazz, state)) return false
|
||||
}
|
||||
ImportType.STATIC -> {
|
||||
val className = StringUtil.getPackageName(implicitImport.name)
|
||||
val memberName = StringUtil.getShortName(implicitImport.name)
|
||||
if (StringUtil.isEmptyOrSpaces(className) || StringUtil.isEmptyOrSpaces(memberName)) continue@loop
|
||||
val clazz = facade.findClass(className, file.resolveScope) ?: continue@loop
|
||||
if (ResolveUtil.shouldProcessMethods (hint)) {
|
||||
for (method in clazz.findMethodsByName(memberName, true)) {
|
||||
if (!ResolveUtil.processElement(processor, method, state)) return false
|
||||
}
|
||||
}
|
||||
if (ResolveUtil.shouldProcessProperties(hint)) {
|
||||
val field = clazz.findFieldByName(memberName, true) ?: continue@loop
|
||||
if (!ResolveUtil.processElement(processor, field, state)) return false
|
||||
}
|
||||
}
|
||||
ImportType.STAR -> {
|
||||
val pckg = facade.findPackage(implicitImport.name) ?: continue@loop
|
||||
if (!pckg.processDeclarations(packageSkipper, state, lastParent, place)) return false
|
||||
}
|
||||
ImportType.STATIC_STAR -> {
|
||||
val clazz = facade.findClass(implicitImport.name, file.resolveScope) ?: continue@loop
|
||||
if (!clazz.processDeclarations(processor, state, lastParent, place)) return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -247,6 +247,7 @@
|
||||
<methodComparator implementation="org.jetbrains.plugins.groovy.lang.resolve.GrDefaultMethodComparator" order="last"/>
|
||||
<expectedPackageNameProvider implementation="org.jetbrains.plugins.groovy.lang.resolve.DefaultExpectedPackageNameProvider"
|
||||
order="last"/>
|
||||
<importContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.DefaultImportContributor"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.properties">
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 org.jetbrains.plugins.groovy.lang.resolve
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
|
||||
|
||||
@CompileStatic
|
||||
class GrImportContributorTest extends LightGroovyTestCase {
|
||||
|
||||
LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
fixture.enableInspections(GrUnresolvedAccessInspection)
|
||||
fixture.addClass '''
|
||||
package foo.bar;
|
||||
public class MyClass {
|
||||
public static Object BAR = null;
|
||||
public static void foo() {}
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
void 'test regular import'() {
|
||||
PlatformTestUtil.registerExtension(GrImportContributor.EP_NAME, {
|
||||
[new Import("foo.bar.MyClass", ImportType.REGULAR)]
|
||||
} as GrImportContributor, testRootDisposable)
|
||||
fixture.with {
|
||||
configureByText('a.groovy', 'new MyClass()')
|
||||
checkHighlighting()
|
||||
}
|
||||
}
|
||||
|
||||
void 'test static import method'() {
|
||||
PlatformTestUtil.registerExtension(GrImportContributor.EP_NAME, {
|
||||
[new Import("foo.bar.MyClass.foo", ImportType.STATIC)]
|
||||
} as GrImportContributor, testRootDisposable)
|
||||
fixture.with {
|
||||
configureByText('a.groovy', 'foo()')
|
||||
checkHighlighting()
|
||||
}
|
||||
}
|
||||
|
||||
void 'test static import field'() {
|
||||
PlatformTestUtil.registerExtension(GrImportContributor.EP_NAME, {
|
||||
[new Import("foo.bar.MyClass.BAR", ImportType.STATIC)]
|
||||
} as GrImportContributor, testRootDisposable)
|
||||
fixture.with {
|
||||
configureByText('a.groovy', 'println BAR')
|
||||
checkHighlighting()
|
||||
}
|
||||
}
|
||||
|
||||
void 'test star import'() {
|
||||
PlatformTestUtil.registerExtension(GrImportContributor.EP_NAME, {
|
||||
[new Import("foo.bar", ImportType.STAR)]
|
||||
} as GrImportContributor, testRootDisposable)
|
||||
fixture.with {
|
||||
configureByText('a.groovy', 'new MyClass()')
|
||||
checkHighlighting()
|
||||
}
|
||||
}
|
||||
|
||||
void 'test static star import'() {
|
||||
PlatformTestUtil.registerExtension(GrImportContributor.EP_NAME, {
|
||||
[new Import("foo.bar.MyClass", ImportType.STATIC_STAR)]
|
||||
} as GrImportContributor, testRootDisposable)
|
||||
fixture.with {
|
||||
configureByText('a.groovy', 'println foo()\n println BAR')
|
||||
checkHighlighting()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user