Rename module jet.as.java.psi -> light-classes
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsEnumConstantImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFieldImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsRepositoryPsiElement;
|
||||
import com.intellij.psi.impl.java.stubs.*;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
|
||||
class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
public static final Key<PsiElement> ORIGIN_ELEMENT = Key.create("ORIGIN_ELEMENT");
|
||||
private final StubPsiFactory delegate = new ClsStubPsiFactory();
|
||||
|
||||
public static JetDeclaration getOriginalDeclaration(PsiMember member) {
|
||||
if (member instanceof ClsRepositoryPsiElement<?>) {
|
||||
StubElement stubElement = ((ClsRepositoryPsiElement<?>) member).getStub();
|
||||
if (stubElement instanceof UserDataHolder) {
|
||||
PsiElement original = ((UserDataHolder) stubElement).getUserData(ORIGIN_ELEMENT);
|
||||
if (original instanceof JetDeclaration) {
|
||||
return (JetDeclaration) original;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass createClass(PsiClassStub stub) {
|
||||
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||
if (origin == null) return delegate.createClass(stub);
|
||||
|
||||
return new ClsClassImpl(stub) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return origin;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiAnnotation createAnnotation(PsiAnnotationStub stub) {
|
||||
return delegate.createAnnotation(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClassInitializer createClassInitializer(PsiClassInitializerStub stub) {
|
||||
return delegate.createClassInitializer(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiReferenceList createClassReferenceList(PsiClassReferenceListStub stub) {
|
||||
return delegate.createClassReferenceList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiField createField(PsiFieldStub stub) {
|
||||
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||
if (origin == null) return delegate.createField(stub);
|
||||
if (stub.isEnumConstant()) {
|
||||
return new ClsEnumConstantImpl(stub) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return origin;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return new ClsFieldImpl(stub) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return origin;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiImportList createImportList(PsiImportListStub stub) {
|
||||
return delegate.createImportList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiImportStatementBase createImportStatement(PsiImportStatementStub stub) {
|
||||
return delegate.createImportStatement(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiMethod createMethod(PsiMethodStub stub) {
|
||||
return delegate.createMethod(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiModifierList createModifierList(PsiModifierListStub stub) {
|
||||
return delegate.createModifierList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiParameter createParameter(PsiParameterStub stub) {
|
||||
return delegate.createParameter(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiParameterList createParameterList(PsiParameterListStub stub) {
|
||||
return delegate.createParameterList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeParameter createTypeParameter(PsiTypeParameterStub stub) {
|
||||
return delegate.createTypeParameter(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeParameterList createTypeParameterList(PsiTypeParameterListStub stub) {
|
||||
return delegate.createTypeParameterList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiAnnotationParameterList createAnnotationParameterList(PsiAnnotationParameterListStub stub) {
|
||||
return delegate.createAnnotationParameterList(stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiNameValuePair createNameValuePair(PsiNameValuePairStub stub) {
|
||||
return delegate.createNameValuePair(stub);
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.light.AbstractLightClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
/**
|
||||
* This class serves as a workaround for usages of {@link JavaElementFinder#findClasses} which eventually only need names of files
|
||||
* containing the class. When queried for a package class (e.g. test/TestPackage), {@code findClasses} along with a
|
||||
* {@link KotlinLightClassForPackage} would also return multiple instances of this class for each file present in the package. The client
|
||||
* code can make use of every file in the package then, since {@code getContainingFile} of these instances will represent the whole package.
|
||||
* <p/>
|
||||
* See {@link LineBreakpoint#findClassCandidatesInSourceContent} for the primary usage this was introduced
|
||||
*/
|
||||
public class FakeLightClassForFileOfPackage extends AbstractLightClass implements KotlinLightClass, JetJavaMirrorMarker {
|
||||
private final KotlinLightClassForPackage delegate;
|
||||
private final JetFile file;
|
||||
|
||||
public FakeLightClassForFileOfPackage(
|
||||
@NotNull PsiManager manager, @NotNull KotlinLightClassForPackage delegate, @NotNull JetFile file
|
||||
) {
|
||||
super(manager);
|
||||
this.delegate = delegate;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JetClassOrObject getOrigin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile getContainingFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// This is intentionally false to prevent using this as a real class
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getFqName() {
|
||||
return delegate.getFqName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new FakeLightClassForFileOfPackage(getManager(), delegate, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return JetLanguage.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetEnumEntry;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.java.KotlinFinderMarker;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.NamePackage;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class JavaElementFinder extends PsiElementFinder implements KotlinFinderMarker {
|
||||
|
||||
@NotNull
|
||||
public static JavaElementFinder getInstance(@NotNull Project project) {
|
||||
PsiElementFinder[] extensions = Extensions.getArea(project).getExtensionPoint(PsiElementFinder.EP_NAME).getExtensions();
|
||||
for (PsiElementFinder extension : extensions) {
|
||||
if (extension instanceof JavaElementFinder) {
|
||||
return (JavaElementFinder) extension;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException(JavaElementFinder.class.getSimpleName() + " is not found for project " + project);
|
||||
}
|
||||
|
||||
private final Project project;
|
||||
private final PsiManager psiManager;
|
||||
private final LightClassGenerationSupport lightClassGenerationSupport;
|
||||
|
||||
private final CachedValue<SLRUCache<FindClassesRequest, PsiClass[]>> findClassesCache;
|
||||
|
||||
public JavaElementFinder(
|
||||
@NotNull Project project,
|
||||
@NotNull LightClassGenerationSupport lightClassGenerationSupport
|
||||
) {
|
||||
this.project = project;
|
||||
this.psiManager = PsiManager.getInstance(project);
|
||||
this.lightClassGenerationSupport = lightClassGenerationSupport;
|
||||
this.findClassesCache = CachedValuesManager.getManager(project).createCachedValue(
|
||||
new CachedValueProvider<SLRUCache<FindClassesRequest, PsiClass[]>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<SLRUCache<FindClassesRequest, PsiClass[]>> compute() {
|
||||
return new Result<SLRUCache<FindClassesRequest, PsiClass[]>>(
|
||||
new SLRUCache<FindClassesRequest, PsiClass[]>(30, 10) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] createValue(FindClassesRequest key) {
|
||||
return doFindClasses(key.fqName, key.scope);
|
||||
}
|
||||
},
|
||||
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
);
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||
PsiClass[] allClasses = findClasses(qualifiedName, scope);
|
||||
return allClasses.length > 0 ? allClasses[0] : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] findClasses(@NotNull String qualifiedNameString, @NotNull GlobalSearchScope scope) {
|
||||
SLRUCache<FindClassesRequest, PsiClass[]> value = findClassesCache.getValue();
|
||||
synchronized (value) {
|
||||
return value.get(new FindClassesRequest(qualifiedNameString, scope));
|
||||
}
|
||||
}
|
||||
|
||||
private PsiClass[] doFindClasses(String qualifiedNameString, GlobalSearchScope scope) {
|
||||
if (!NamePackage.isValidJavaFqName(qualifiedNameString)) {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||
|
||||
FqName qualifiedName = new FqName(qualifiedNameString);
|
||||
|
||||
findClassesAndObjects(qualifiedName, scope, answer);
|
||||
|
||||
if (PackageClassUtils.isPackageClassFqName(qualifiedName)) {
|
||||
answer.addAll(lightClassGenerationSupport.getPackageClasses(qualifiedName.parent(), scope));
|
||||
}
|
||||
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
// Finds explicitly declared classes and objects, not package classes
|
||||
private void findClassesAndObjects(FqName qualifiedName, GlobalSearchScope scope, List<PsiClass> answer) {
|
||||
Collection<JetClassOrObject> classOrObjectDeclarations =
|
||||
lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName, scope);
|
||||
|
||||
for (JetClassOrObject declaration : classOrObjectDeclarations) {
|
||||
if (!(declaration instanceof JetEnumEntry)) {
|
||||
PsiClass lightClass = LightClassUtil.getPsiClass(declaration);
|
||||
if (lightClass != null) {
|
||||
answer.add(lightClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
Collection<JetClassOrObject> declarations = lightClassGenerationSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
|
||||
Set<String> answer = Sets.newHashSet();
|
||||
answer.add(PackageClassUtils.getPackageClassName(packageFQN));
|
||||
|
||||
for (JetClassOrObject declaration : declarations) {
|
||||
String name = declaration.getName();
|
||||
if (name != null) {
|
||||
answer.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiPackage findPackage(@NotNull String qualifiedNameString) {
|
||||
if (!NamePackage.isValidJavaFqName(qualifiedNameString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FqName fqName = new FqName(qualifiedNameString);
|
||||
|
||||
// allScope() because the contract says that the whole project
|
||||
GlobalSearchScope allScope = GlobalSearchScope.allScope(project);
|
||||
if (lightClassGenerationSupport.packageExists(fqName, allScope)) {
|
||||
return new JetLightPackage(psiManager, fqName, allScope);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
Collection<FqName> subpackages = lightClassGenerationSupport.getSubPackages(packageFQN, scope);
|
||||
|
||||
Collection<PsiPackage> answer = Collections2.transform(subpackages, new Function<FqName, PsiPackage>() {
|
||||
@Override
|
||||
public PsiPackage apply(@Nullable FqName input) {
|
||||
return new JetLightPackage(psiManager, input, scope);
|
||||
}
|
||||
});
|
||||
|
||||
return answer.toArray(new PsiPackage[answer.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
answer.addAll(lightClassGenerationSupport.getPackageClasses(packageFQN, scope));
|
||||
|
||||
Collection<JetClassOrObject> declarations = lightClassGenerationSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
for (JetClassOrObject declaration : declarations) {
|
||||
PsiClass aClass = LightClassUtil.getPsiClass(declaration);
|
||||
if (aClass != null) {
|
||||
answer.add(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
// implements a method added in 14.1
|
||||
@NotNull
|
||||
public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
Collection<JetFile> result = lightClassGenerationSupport.findFilesForPackage(packageFQN, scope);
|
||||
return result.toArray(new PsiFile[result.size()]);
|
||||
}
|
||||
|
||||
// implements a method added in IDEA 14.1
|
||||
@SuppressWarnings({"UnusedDeclaration", "MethodMayBeStatic"})
|
||||
@Nullable
|
||||
public Condition<PsiFile> getPackageFilesFilter(@NotNull final PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
return new Condition<PsiFile>() {
|
||||
@Override
|
||||
public boolean value(@Nullable PsiFile input) {
|
||||
if (!(input instanceof JetFile)) {
|
||||
return true;
|
||||
}
|
||||
return psiPackage.getQualifiedName().equals(((JetFile) input).getPackageFqName().asString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class FindClassesRequest {
|
||||
private final String fqName;
|
||||
private final GlobalSearchScope scope;
|
||||
|
||||
private FindClassesRequest(@NotNull String fqName, @NotNull GlobalSearchScope scope) {
|
||||
this.fqName = fqName;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FindClassesRequest request = (FindClassesRequest) o;
|
||||
|
||||
if (!fqName.equals(request.fqName)) return false;
|
||||
if (!scope.equals(request.scope)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fqName.hashCode();
|
||||
result = 31 * result + (scope.hashCode());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.file.PsiPackageImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
public class JetLightPackage extends PsiPackageImpl {
|
||||
|
||||
private final FqName fqName;
|
||||
private final GlobalSearchScope scope;
|
||||
|
||||
public JetLightPackage(PsiManager manager, FqName qualifiedName, GlobalSearchScope scope) {
|
||||
super(manager, qualifiedName.asString());
|
||||
this.fqName = qualifiedName;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new JetLightPackage(getManager(), fqName, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return LightClassGenerationSupport.getInstance(getProject()).packageExists(fqName, scope);
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.*
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
/**
|
||||
* Tested in OutOfBlockModificationTestGenerated
|
||||
*/
|
||||
public class KotlinCodeBlockModificationListener(modificationTracker: PsiModificationTracker) : PsiTreeChangePreprocessor {
|
||||
private val myModificationTracker = modificationTracker as PsiModificationTrackerImpl
|
||||
|
||||
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
||||
if (event.getFile() !is JetFile) return
|
||||
|
||||
when (event.getCode()) {
|
||||
BEFORE_CHILDREN_CHANGE,
|
||||
BEFORE_PROPERTY_CHANGE,
|
||||
BEFORE_CHILD_MOVEMENT,
|
||||
BEFORE_CHILD_REPLACEMENT,
|
||||
BEFORE_CHILD_ADDITION,
|
||||
BEFORE_CHILD_REMOVAL -> {
|
||||
// skip
|
||||
}
|
||||
|
||||
CHILD_ADDED,
|
||||
CHILD_REMOVED,
|
||||
CHILD_REPLACED -> {
|
||||
processChange(event.getParent(), event.getOldChild(), event.getChild())
|
||||
}
|
||||
|
||||
CHILDREN_CHANGED -> {
|
||||
if (!event.isGenericChange()) {
|
||||
processChange(event.getParent(), event.getParent(), null)
|
||||
}
|
||||
}
|
||||
|
||||
CHILD_MOVED,
|
||||
PROPERTY_CHANGED -> {
|
||||
myModificationTracker.incCounter()
|
||||
}
|
||||
|
||||
else -> LOG.error("Unknown code:" + event.getCode())
|
||||
}
|
||||
}
|
||||
|
||||
private fun processChange(parent: PsiElement?, child1: PsiElement?, child2: PsiElement?) {
|
||||
try {
|
||||
if (!isInsideCodeBlock(parent)) {
|
||||
if (parent != null && parent.getContainingFile() is JetFile) {
|
||||
myModificationTracker.incCounter()
|
||||
}
|
||||
else {
|
||||
myModificationTracker.incOutOfCodeBlockModificationCounter()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (containsClassesInside(child1) || (child2 != child1 && containsClassesInside(child2))) {
|
||||
myModificationTracker.incCounter()
|
||||
}
|
||||
}
|
||||
catch (e: PsiInvalidElementAccessException) {
|
||||
myModificationTracker.incCounter() // Shall not happen actually, just a pre-release paranoia
|
||||
}
|
||||
}
|
||||
|
||||
class object {
|
||||
private val LOG = Logger.getInstance("#org.jetbrains.jet.asJava.JetCodeBlockModificationListener")
|
||||
|
||||
private fun containsClassesInside(element: PsiElement?): Boolean {
|
||||
if (element == null) return false
|
||||
if (element is PsiClass) return true
|
||||
|
||||
var child = element.getFirstChild()
|
||||
while (child != null) {
|
||||
if (containsClassesInside(child)) return true
|
||||
child = child!!.getNextSibling()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isInsideCodeBlock(element: PsiElement?): Boolean {
|
||||
if (element is PsiFileSystemItem) return false
|
||||
if (element == null || element.getParent() == null) return true
|
||||
|
||||
val blockDeclarationCandidate = JetPsiUtil.getTopmostParentOfTypes(
|
||||
element,
|
||||
javaClass<JetProperty>(),
|
||||
javaClass<JetNamedFunction>())
|
||||
|
||||
when (blockDeclarationCandidate) {
|
||||
is JetNamedFunction -> {
|
||||
val function = blockDeclarationCandidate : JetNamedFunction
|
||||
if (function.hasBlockBody() && function.getBodyExpression().isAncestorOf(element)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (function.hasDeclaredReturnType() && function.getInitializer().isAncestorOf(element)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
is JetProperty -> {
|
||||
val property = blockDeclarationCandidate : JetProperty
|
||||
for (accessor in property.getAccessors()) {
|
||||
when {
|
||||
accessor.getInitializer().isAncestorOf(element) -> return true
|
||||
accessor.getBodyExpression().isAncestorOf(element) -> return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun PsiElement?.isAncestorOf(element: PsiElement) = PsiTreeUtil.isAncestor(this, element, false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.ClassFileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.PsiClassHolderFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.jet.codegen.KotlinCodegenFacade;
|
||||
import org.jetbrains.jet.codegen.PackageCodegen;
|
||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.Progress;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetScript;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.diagnostics.Diagnostics;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
|
||||
public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostics> implements CachedValueProvider<T> {
|
||||
|
||||
@NotNull
|
||||
public static KotlinJavaFileStubProvider<KotlinPackageLightClassData> createForPackageClass(
|
||||
@NotNull final Project project,
|
||||
@NotNull final FqName packageFqName,
|
||||
@NotNull final GlobalSearchScope searchScope
|
||||
) {
|
||||
return new KotlinJavaFileStubProvider<KotlinPackageLightClassData>(
|
||||
project,
|
||||
false,
|
||||
new StubGenerationStrategy<KotlinPackageLightClassData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext getContext(@NotNull Collection<JetFile> files) {
|
||||
return LightClassGenerationSupport.getInstance(project).getContextForPackage(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> getFiles() {
|
||||
// Don't memoize this, it can be called again after an out-of-code-block modification occurs,
|
||||
// and the set of files changes
|
||||
return LightClassGenerationSupport.getInstance(project).findFilesForPackage(packageFqName, searchScope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KotlinPackageLightClassData createLightClassData(
|
||||
PsiJavaFileStub javaFileStub,
|
||||
BindingContext bindingContext,
|
||||
Diagnostics extraDiagnostics
|
||||
) {
|
||||
return new KotlinPackageLightClassData(javaFileStub, extraDiagnostics);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getPackageFqName() {
|
||||
return packageFqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||
return new GenerationState.GenerateClassFilter() {
|
||||
@Override
|
||||
public boolean shouldProcessClass(JetClassOrObject classOrObject) {
|
||||
// Top-level classes and such should not be generated for performance reasons.
|
||||
// Local classes in top-level functions must still be generated
|
||||
return JetPsiUtil.isLocal(classOrObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldProcessScript(JetScript script) {
|
||||
// Scripts yield top-level classes, and should not be generated
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationState state, @NotNull Collection<JetFile> files) {
|
||||
PackageCodegen codegen = state.getFactory().forPackage(packageFqName, files);
|
||||
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION);
|
||||
state.getFactory().asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StubGenerationStrategy.class.getName() + " for package class";
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static KotlinJavaFileStubProvider<OutermostKotlinClassLightClassData> createForDeclaredClass(@NotNull final JetClassOrObject classOrObject) {
|
||||
return new KotlinJavaFileStubProvider<OutermostKotlinClassLightClassData>(
|
||||
classOrObject.getProject(),
|
||||
classOrObject.isLocal(),
|
||||
new StubGenerationStrategy<OutermostKotlinClassLightClassData>() {
|
||||
private JetFile getFile() {
|
||||
return classOrObject.getContainingJetFile();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LightClassConstructionContext getContext(@NotNull Collection<JetFile> files) {
|
||||
return LightClassGenerationSupport.getInstance(classOrObject.getProject()).getContextForClassOrObject(classOrObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OutermostKotlinClassLightClassData createLightClassData(
|
||||
PsiJavaFileStub javaFileStub,
|
||||
BindingContext bindingContext,
|
||||
Diagnostics extraDiagnostics
|
||||
) {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject);
|
||||
if (classDescriptor == null) {
|
||||
return new OutermostKotlinClassLightClassData(
|
||||
javaFileStub, extraDiagnostics, FqName.ROOT, classOrObject,
|
||||
null, Collections.<JetClassOrObject, InnerKotlinClassLightClassData>emptyMap()
|
||||
);
|
||||
}
|
||||
|
||||
FqName fqName = predictClassFqName(bindingContext, classDescriptor);
|
||||
Collection<ClassDescriptor> allInnerClasses = CodegenBinding.getAllInnerClasses(bindingContext, classDescriptor);
|
||||
|
||||
Map<JetClassOrObject, InnerKotlinClassLightClassData> innerClassesMap = ContainerUtil.newHashMap();
|
||||
for (ClassDescriptor innerClassDescriptor : allInnerClasses) {
|
||||
PsiElement declaration = descriptorToDeclaration(innerClassDescriptor);
|
||||
if (!(declaration instanceof JetClassOrObject)) continue;
|
||||
JetClassOrObject innerClass = (JetClassOrObject) declaration;
|
||||
|
||||
InnerKotlinClassLightClassData innerLightClassData = new InnerKotlinClassLightClassData(
|
||||
predictClassFqName(bindingContext, innerClassDescriptor),
|
||||
innerClass,
|
||||
innerClassDescriptor
|
||||
);
|
||||
|
||||
innerClassesMap.put(innerClass, innerLightClassData);
|
||||
}
|
||||
|
||||
return new OutermostKotlinClassLightClassData(
|
||||
javaFileStub,
|
||||
extraDiagnostics,
|
||||
fqName,
|
||||
classOrObject,
|
||||
classDescriptor,
|
||||
innerClassesMap
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private FqName predictClassFqName(BindingContext bindingContext, ClassDescriptor classDescriptor) {
|
||||
Type asmType = CodegenBinding.getAsmType(bindingContext, classDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
return JvmClassName.byInternalName(asmType.getClassName().replace('.', '/')).getFqNameForClassNameWithoutDollars();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> getFiles() {
|
||||
return Collections.singletonList(getFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getPackageFqName() {
|
||||
return getFile().getPackageFqName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationState.GenerateClassFilter getGenerateClassFilter() {
|
||||
return new GenerationState.GenerateClassFilter() {
|
||||
@Override
|
||||
public boolean shouldProcessClass(JetClassOrObject generatedClassOrObject) {
|
||||
// Trivial: generate and analyze class we are interested in.
|
||||
if (generatedClassOrObject == classOrObject) return true;
|
||||
|
||||
// Process all parent classes as they are context for current class
|
||||
// Process child classes because they probably affect members (heuristic)
|
||||
if (PsiTreeUtil.isAncestor(generatedClassOrObject, classOrObject, true) ||
|
||||
PsiTreeUtil.isAncestor(classOrObject, generatedClassOrObject, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (generatedClassOrObject.isLocal() && classOrObject.isLocal()) {
|
||||
// Local classes should be process by CodegenAnnotatingVisitor to
|
||||
// decide what class they should be placed in.
|
||||
//
|
||||
// Example:
|
||||
// class A
|
||||
// fun foo() {
|
||||
// trait Z: A {}
|
||||
// fun bar() {
|
||||
// class <caret>O2: Z {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: current method will process local classes in irrelevant declarations, it should be fixed.
|
||||
PsiElement commonParent = PsiTreeUtil.findCommonParent(generatedClassOrObject, classOrObject);
|
||||
return commonParent != null && !(commonParent instanceof PsiFile);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldProcessScript(JetScript script) {
|
||||
// We generate all enclosing classes
|
||||
return PsiTreeUtil.isAncestor(script, classOrObject, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationState state, @NotNull Collection<JetFile> files) {
|
||||
PackageCodegen packageCodegen = state.getFactory().forPackage(getPackageFqName(), files);
|
||||
packageCodegen.generateClassOrObject(classOrObject);
|
||||
state.getFactory().asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StubGenerationStrategy.class.getName() + " for explicit class " + classOrObject.getName();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(KotlinJavaFileStubProvider.class);
|
||||
|
||||
private final Project project;
|
||||
private final StubGenerationStrategy<T> stubGenerationStrategy;
|
||||
private final boolean local;
|
||||
|
||||
private KotlinJavaFileStubProvider(
|
||||
@NotNull Project project,
|
||||
boolean local,
|
||||
@NotNull StubGenerationStrategy<T> stubGenerationStrategy
|
||||
) {
|
||||
this.project = project;
|
||||
this.stubGenerationStrategy = stubGenerationStrategy;
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<T> compute() {
|
||||
FqName packageFqName = stubGenerationStrategy.getPackageFqName();
|
||||
Collection<JetFile> files = stubGenerationStrategy.getFiles();
|
||||
|
||||
checkForBuiltIns(packageFqName, files);
|
||||
|
||||
LightClassConstructionContext context = stubGenerationStrategy.getContext(files);
|
||||
|
||||
PsiJavaFileStub javaFileStub = createJavaFileStub(packageFqName, getRepresentativeVirtualFile(files));
|
||||
BindingContext bindingContext;
|
||||
BindingTraceContext forExtraDiagnostics = new BindingTraceContext();
|
||||
try {
|
||||
Stack<StubElement> stubStack = new Stack<StubElement>();
|
||||
stubStack.push(javaFileStub);
|
||||
|
||||
GenerationState state = new GenerationState(
|
||||
project,
|
||||
new KotlinLightClassBuilderFactory(stubStack),
|
||||
Progress.DEAF,
|
||||
context.getModule(),
|
||||
context.getBindingContext(),
|
||||
Lists.newArrayList(files),
|
||||
/*disable not-null assertions*/false, false,
|
||||
/*generateClassFilter=*/stubGenerationStrategy.getGenerateClassFilter(),
|
||||
/*disableInline=*/false,
|
||||
/*disableOptimization=*/false,
|
||||
null,
|
||||
null,
|
||||
forExtraDiagnostics,
|
||||
null
|
||||
);
|
||||
KotlinCodegenFacade.prepareForCompilation(state);
|
||||
|
||||
bindingContext = state.getBindingContext();
|
||||
|
||||
stubGenerationStrategy.generate(state, files);
|
||||
|
||||
StubElement pop = stubStack.pop();
|
||||
if (pop != javaFileStub) {
|
||||
LOG.error("Unbalanced stack operations: " + pop);
|
||||
}
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
logErrorWithOSInfo(e, packageFqName, null);
|
||||
throw e;
|
||||
}
|
||||
|
||||
Diagnostics extraDiagnostics = forExtraDiagnostics.getBindingContext().getDiagnostics();
|
||||
return Result.create(
|
||||
stubGenerationStrategy.createLightClassData(javaFileStub, bindingContext, extraDiagnostics),
|
||||
local ? PsiModificationTracker.MODIFICATION_COUNT : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiJavaFileStub createJavaFileStub(@NotNull final FqName packageFqName, @NotNull VirtualFile virtualFile) {
|
||||
PsiManager manager = PsiManager.getInstance(project);
|
||||
|
||||
final PsiJavaFileStubImpl javaFileStub = new PsiJavaFileStubImpl(packageFqName.asString(), true);
|
||||
javaFileStub.setPsiFactory(new ClsWrapperStubPsiFactory());
|
||||
|
||||
ClsFileImpl fakeFile =
|
||||
new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, virtualFile)) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassHolderFileStub getStub() {
|
||||
return javaFileStub;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
return packageFqName.asString();
|
||||
}
|
||||
};
|
||||
|
||||
fakeFile.setPhysical(false);
|
||||
javaFileStub.setPsi(fakeFile);
|
||||
return javaFileStub;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static VirtualFile getRepresentativeVirtualFile(@NotNull Collection<JetFile> files) {
|
||||
JetFile firstFile = files.iterator().next();
|
||||
VirtualFile virtualFile = files.size() == 1 ? firstFile.getVirtualFile() : new LightVirtualFile();
|
||||
assert virtualFile != null : "No virtual file for " + firstFile;
|
||||
return virtualFile;
|
||||
}
|
||||
|
||||
private static void checkForBuiltIns(@NotNull FqName fqName, @NotNull Collection<JetFile> files) {
|
||||
for (JetFile file : files) {
|
||||
if (LightClassUtil.belongsToKotlinBuiltIns(file)) {
|
||||
// We may not fail later due to some luck, but generating JetLightClasses for built-ins is a bad idea anyways
|
||||
// If it fails later, there will be an exception logged
|
||||
logErrorWithOSInfo(null, fqName, file.getVirtualFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void logErrorWithOSInfo(@Nullable Throwable cause, @NotNull FqName fqName, @Nullable VirtualFile virtualFile) {
|
||||
String path = virtualFile == null ? "<null>" : virtualFile.getPath();
|
||||
LOG.error(
|
||||
"Could not generate LightClass for " + fqName + " declared in " + path + "\n" +
|
||||
"built-ins dir URL is " + LightClassUtil.getBuiltInsDirUrl() + "\n" +
|
||||
"System: " + SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION + " Java Runtime: " + SystemInfo.JAVA_RUNTIME_VERSION,
|
||||
cause);
|
||||
}
|
||||
|
||||
private interface StubGenerationStrategy<T extends WithFileStubAndExtraDiagnostics> {
|
||||
@NotNull Collection<JetFile> getFiles();
|
||||
@NotNull FqName getPackageFqName();
|
||||
|
||||
@NotNull LightClassConstructionContext getContext(@NotNull Collection<JetFile> files);
|
||||
@NotNull T createLightClassData(PsiJavaFileStub javaFileStub, BindingContext bindingContext, Diagnostics extraDiagnostics);
|
||||
|
||||
GenerationState.GenerateClassFilter getGenerateClassFilter();
|
||||
void generate(@NotNull GenerationState state, @NotNull Collection<JetFile> files);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
|
||||
public trait KotlinLightClass : PsiClass, KotlinLightElement<JetClassOrObject, PsiClass> {
|
||||
val fqName: FqName
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderMode;
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin;
|
||||
|
||||
/*package*/ class KotlinLightClassBuilderFactory implements ClassBuilderFactory {
|
||||
private final Stack<StubElement> stubStack;
|
||||
|
||||
public KotlinLightClassBuilderFactory(Stack<StubElement> stubStack) {
|
||||
this.stubStack = stubStack;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return ClassBuilderMode.LIGHT_CLASSES;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) {
|
||||
return new StubClassBuilder(stubStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asText(ClassBuilder builder) {
|
||||
throw new UnsupportedOperationException("asText is not implemented"); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] asBytes(ClassBuilder builder) {
|
||||
throw new UnsupportedOperationException("asBytes is not implemented"); // TODO
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class KotlinLightClassForAnonymousDeclaration extends KotlinLightClassForExplicitDeclaration implements PsiAnonymousClass {
|
||||
private static final Logger LOG = Logger.getInstance(KotlinLightClassForAnonymousDeclaration.class);
|
||||
|
||||
private SoftReference<PsiClassType> cachedBaseType = null;
|
||||
|
||||
KotlinLightClassForAnonymousDeclaration(@NotNull PsiManager manager, @NotNull FqName name, @NotNull JetClassOrObject classOrObject) {
|
||||
super(manager, name, classOrObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaCodeReferenceElement getBaseClassReference() {
|
||||
Project project = classOrObject.getProject();
|
||||
return JavaPsiFacade.getElementFactory(project).createReferenceElementByFQClassName(
|
||||
getFirstSupertypeFQName(), GlobalSearchScope.allScope(project)
|
||||
);
|
||||
}
|
||||
|
||||
private String getFirstSupertypeFQName() {
|
||||
ClassDescriptor descriptor = getDescriptor();
|
||||
if (descriptor == null) return CommonClassNames.JAVA_LANG_OBJECT;
|
||||
|
||||
Collection<JetType> superTypes = descriptor.getTypeConstructor().getSupertypes();
|
||||
|
||||
if (superTypes.isEmpty()) return CommonClassNames.JAVA_LANG_OBJECT;
|
||||
|
||||
JetType superType = superTypes.iterator().next();
|
||||
DeclarationDescriptor superClassDescriptor = superType.getConstructor().getDeclarationDescriptor();
|
||||
|
||||
if (superClassDescriptor == null) {
|
||||
LOG.error("No declaration descriptor for supertype " + superType + " of " + getDescriptor());
|
||||
// return java.lang.Object for recovery
|
||||
return CommonClassNames.JAVA_LANG_OBJECT;
|
||||
}
|
||||
|
||||
return DescriptorUtils.getFqName(superClassDescriptor).asString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public synchronized PsiClassType getBaseClassType() {
|
||||
PsiClassType type = null;
|
||||
if (cachedBaseType != null) type = cachedBaseType.get();
|
||||
if (type != null && type.isValid()) return type;
|
||||
|
||||
type = JavaPsiFacade.getInstance(classOrObject.getProject()).getElementFactory().createType(getBaseClassReference());
|
||||
cachedBaseType = new SoftReference<PsiClassType>(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiExpressionList getArgumentList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInQualifiedNew() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava
|
||||
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||
import org.jetbrains.jet.lang.psi.JetEnumEntry
|
||||
import com.intellij.psi.PsiEnumConstantInitializer
|
||||
import com.intellij.psi.PsiEnumConstant
|
||||
|
||||
public class KotlinLightClassForEnumEntry(
|
||||
psiManager: PsiManager,
|
||||
fqName: FqName,
|
||||
enumEntry: JetEnumEntry,
|
||||
private val enumConstant: PsiEnumConstant
|
||||
): KotlinLightClassForAnonymousDeclaration(psiManager, fqName, enumEntry), PsiEnumConstantInitializer {
|
||||
override fun getEnumConstant(): PsiEnumConstant = enumConstant
|
||||
}
|
||||
+604
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NullableLazyValue;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
|
||||
import com.intellij.psi.impl.light.LightClass;
|
||||
import com.intellij.psi.impl.light.LightMethod;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.stubs.PsiClassHolderFileStub;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
|
||||
public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightClass implements JetJavaMirrorMarker {
|
||||
private final static Key<CachedValue<OutermostKotlinClassLightClassData>> JAVA_API_STUB = Key.create("JAVA_API_STUB");
|
||||
|
||||
@Nullable
|
||||
public static KotlinLightClassForExplicitDeclaration create(@NotNull PsiManager manager, @NotNull JetClassOrObject classOrObject) {
|
||||
if (LightClassUtil.belongsToKotlinBuiltIns(classOrObject.getContainingJetFile())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FqName fqName = predictFqName(classOrObject);
|
||||
if (fqName == null) return null;
|
||||
|
||||
if (classOrObject instanceof JetObjectDeclaration && ((JetObjectDeclaration) classOrObject).isObjectLiteral()) {
|
||||
return new KotlinLightClassForAnonymousDeclaration(manager, fqName, classOrObject);
|
||||
}
|
||||
return new KotlinLightClassForExplicitDeclaration(manager, fqName, classOrObject);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FqName predictFqName(@NotNull JetClassOrObject classOrObject) {
|
||||
if (classOrObject.isLocal()) {
|
||||
LightClassDataForKotlinClass data = getLightClassDataExactly(classOrObject);
|
||||
return data == null ? null : data.getJvmQualifiedName();
|
||||
}
|
||||
String internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject);
|
||||
return internalName == null ? null : JvmClassName.byInternalName(internalName).getFqNameForClassNameWithoutDollars();
|
||||
}
|
||||
|
||||
private final FqName classFqName; // FqName of (possibly inner) class
|
||||
protected final JetClassOrObject classOrObject;
|
||||
private PsiClass delegate;
|
||||
|
||||
private final NullableLazyValue<PsiElement> parent = new NullableLazyValue<PsiElement>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement compute() {
|
||||
if (classOrObject.isLocal()) {
|
||||
//noinspection unchecked
|
||||
PsiElement declaration = JetPsiUtil.getTopmostParentOfTypes(
|
||||
classOrObject,
|
||||
JetNamedFunction.class, JetProperty.class, JetClassInitializer.class, JetParameter.class
|
||||
);
|
||||
|
||||
if (declaration instanceof JetParameter) {
|
||||
declaration = PsiTreeUtil.getParentOfType(declaration, JetNamedDeclaration.class);
|
||||
}
|
||||
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction) declaration;
|
||||
return getParentByPsiMethod(LightClassUtil.getLightClassMethod(function), function.getName(), false);
|
||||
}
|
||||
|
||||
// Represent the property as a fake method with the same name
|
||||
if (declaration instanceof JetProperty) {
|
||||
JetProperty property = (JetProperty) declaration;
|
||||
return getParentByPsiMethod(LightClassUtil.getLightClassPropertyMethods(property).getGetter(), property.getName(), true);
|
||||
}
|
||||
|
||||
if (declaration instanceof JetClassInitializer) {
|
||||
PsiElement parent = declaration.getParent();
|
||||
PsiElement grandparent = parent.getParent();
|
||||
|
||||
if (parent instanceof JetClassBody && grandparent instanceof JetClassOrObject) {
|
||||
return LightClassUtil.getPsiClass((JetClassOrObject) grandparent);
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration instanceof JetClass) {
|
||||
return LightClassUtil.getPsiClass((JetClass) declaration);
|
||||
}
|
||||
}
|
||||
|
||||
return classOrObject.getParent() == classOrObject.getContainingFile() ? getContainingFile() : getContainingClass();
|
||||
}
|
||||
|
||||
private PsiElement getParentByPsiMethod(PsiMethod method, final String name, boolean forceMethodWrapping) {
|
||||
if (method == null || name == null) return null;
|
||||
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return null;
|
||||
|
||||
final String currentFileName = classOrObject.getContainingFile().getName();
|
||||
|
||||
boolean createWrapper = forceMethodWrapping;
|
||||
// Use PsiClass wrapper instead of package light class to avoid names like "FooPackage" in Type Hierarchy and related views
|
||||
if (containingClass instanceof KotlinLightClassForPackage) {
|
||||
containingClass = new LightClass(containingClass, JetLanguage.INSTANCE) {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return currentFileName;
|
||||
}
|
||||
};
|
||||
createWrapper = true;
|
||||
}
|
||||
|
||||
if (createWrapper) {
|
||||
return new LightMethod(myManager, method, containingClass, JetLanguage.INSTANCE) {
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return getContainingClass();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private PsiModifierList modifierList;
|
||||
|
||||
private final NullableLazyValue<PsiTypeParameterList> typeParameterList = new NullableLazyValue<PsiTypeParameterList>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiTypeParameterList compute() {
|
||||
return LightClassUtil.buildLightTypeParameterList(KotlinLightClassForExplicitDeclaration.this, classOrObject);
|
||||
}
|
||||
};
|
||||
|
||||
KotlinLightClassForExplicitDeclaration(
|
||||
@NotNull PsiManager manager,
|
||||
@NotNull FqName name,
|
||||
@NotNull JetClassOrObject classOrObject
|
||||
) {
|
||||
super(manager);
|
||||
this.classFqName = name;
|
||||
this.classOrObject = classOrObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JetClassOrObject getOrigin() {
|
||||
return classOrObject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getFqName() {
|
||||
return classFqName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new KotlinLightClassForExplicitDeclaration(getManager(), classFqName, (JetClassOrObject) classOrObject.copy());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass getDelegate() {
|
||||
if (delegate == null) {
|
||||
PsiJavaFileStub javaFileStub = getJavaFileStub();
|
||||
|
||||
PsiClass psiClass = LightClassUtil.findClass(classFqName, javaFileStub);
|
||||
if (psiClass == null) {
|
||||
JetClassOrObject outermostClassOrObject = getOutermostClassOrObject(classOrObject);
|
||||
throw new IllegalStateException("Class was not found " + classFqName + "\n" +
|
||||
"in " + outermostClassOrObject.getContainingFile().getText() + "\n" +
|
||||
"stub: \n" + javaFileStub.getPsi().getText());
|
||||
}
|
||||
delegate = psiClass;
|
||||
}
|
||||
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiJavaFileStub getJavaFileStub() {
|
||||
return getLightClassData().getJavaFileStub();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final ClassDescriptor getDescriptor() {
|
||||
LightClassDataForKotlinClass data = getLightClassDataExactly(classOrObject);
|
||||
return data != null ? data.getDescriptor() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private OutermostKotlinClassLightClassData getLightClassData() {
|
||||
return getLightClassData(classOrObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static OutermostKotlinClassLightClassData getLightClassData(@NotNull JetClassOrObject classOrObject) {
|
||||
JetClassOrObject outermostClassOrObject = getOutermostClassOrObject(classOrObject);
|
||||
return CachedValuesManager.getManager(classOrObject.getProject()).getCachedValue(
|
||||
outermostClassOrObject,
|
||||
JAVA_API_STUB,
|
||||
KotlinJavaFileStubProvider.createForDeclaredClass(outermostClassOrObject),
|
||||
/*trackValue = */false
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LightClassDataForKotlinClass getLightClassDataExactly(JetClassOrObject classOrObject) {
|
||||
OutermostKotlinClassLightClassData data = getLightClassData(classOrObject);
|
||||
return data.getClassOrObject().equals(classOrObject) ? data : data.getAllInnerClasses().get(classOrObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JetClassOrObject getOutermostClassOrObject(@NotNull JetClassOrObject classOrObject) {
|
||||
JetClassOrObject outermostClass = JetPsiUtil.getOutermostClassOrObject(classOrObject);
|
||||
if (outermostClass == null) {
|
||||
throw new IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.getText());
|
||||
}
|
||||
else {
|
||||
return outermostClass;
|
||||
}
|
||||
}
|
||||
|
||||
private final NullableLazyValue<PsiFile> _containingFile = new NullableLazyValue<PsiFile>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiFile compute() {
|
||||
VirtualFile virtualFile = classOrObject.getContainingFile().getVirtualFile();
|
||||
assert virtualFile != null : "No virtual file for " + classOrObject.getText();
|
||||
return new ClsFileImpl((PsiManagerImpl) getManager(), new ClassFileViewProvider(getManager(), virtualFile)) {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
return classOrObject.getContainingJetFile().getPackageFqName().asString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassHolderFileStub getStub() {
|
||||
return getJavaFileStub();
|
||||
}
|
||||
|
||||
@SuppressWarnings("Contract")
|
||||
@Override
|
||||
public boolean processDeclarations(
|
||||
@NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
PsiElement lastParent,
|
||||
@NotNull PsiElement place
|
||||
) {
|
||||
if (!super.processDeclarations(processor, state, lastParent, place)) return false;
|
||||
|
||||
// We have to explicitly process package declarations if current file belongs to default package
|
||||
// so that Java resolve can find classes located in that package
|
||||
String packageName = getPackageName();
|
||||
if (!packageName.isEmpty()) return true;
|
||||
|
||||
PsiPackage aPackage = JavaPsiFacade.getInstance(myManager.getProject()).findPackage(packageName);
|
||||
if (aPackage != null && !aPackage.processDeclarations(processor, state, null, place)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public PsiFile getContainingFile() {
|
||||
return _containingFile.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return classOrObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
return another instanceof PsiClass && Comparing.equal(((PsiClass) another).getQualifiedName(), getQualifiedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getElementIcon(int flags) {
|
||||
throw new UnsupportedOperationException("This should be done byt JetIconProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
KotlinLightClassForExplicitDeclaration aClass = (KotlinLightClassForExplicitDeclaration) o;
|
||||
|
||||
if (!classFqName.equals(aClass.classFqName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return classFqName.hashCode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
if (classOrObject.getParent() == classOrObject.getContainingFile()) return null;
|
||||
return super.getContainingClass();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return parent.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getContext() {
|
||||
return getParent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiTypeParameterList getTypeParameterList() {
|
||||
return typeParameterList.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeParameter[] getTypeParameters() {
|
||||
PsiTypeParameterList typeParameterList = getTypeParameterList();
|
||||
return typeParameterList == null ? PsiTypeParameter.EMPTY_ARRAY : typeParameterList.getTypeParameters();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return classFqName.shortName().asString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getQualifiedName() {
|
||||
return classFqName.asString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
if (modifierList == null) {
|
||||
modifierList = new KotlinLightModifierList(this.getManager(), computeModifiers()) {
|
||||
@Override
|
||||
public PsiAnnotationOwner getDelegate() {
|
||||
return KotlinLightClassForExplicitDeclaration.this.getDelegate().getModifierList();
|
||||
}
|
||||
};
|
||||
}
|
||||
return modifierList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String[] computeModifiers() {
|
||||
Collection<String> psiModifiers = Sets.newHashSet();
|
||||
|
||||
// PUBLIC, PROTECTED, PRIVATE, ABSTRACT, FINAL
|
||||
//noinspection unchecked
|
||||
List<Pair<JetModifierKeywordToken, String>> jetTokenToPsiModifier = Lists.newArrayList(
|
||||
Pair.create(PUBLIC_KEYWORD, PsiModifier.PUBLIC),
|
||||
Pair.create(INTERNAL_KEYWORD, PsiModifier.PUBLIC),
|
||||
Pair.create(PROTECTED_KEYWORD, PsiModifier.PROTECTED),
|
||||
Pair.create(FINAL_KEYWORD, PsiModifier.FINAL));
|
||||
|
||||
for (Pair<JetModifierKeywordToken, String> tokenAndModifier : jetTokenToPsiModifier) {
|
||||
if (classOrObject.hasModifier(tokenAndModifier.first)) {
|
||||
psiModifiers.add(tokenAndModifier.second);
|
||||
}
|
||||
}
|
||||
|
||||
if (classOrObject.hasModifier(PRIVATE_KEYWORD)) {
|
||||
// Top-level private class has PUBLIC visibility in Java
|
||||
// Nested private class has PRIVATE visibility
|
||||
psiModifiers.add(classOrObject.isTopLevel() ? PsiModifier.PUBLIC : PsiModifier.PRIVATE);
|
||||
}
|
||||
|
||||
if (!psiModifiers.contains(PsiModifier.PRIVATE) && !psiModifiers.contains(PsiModifier.PROTECTED)) {
|
||||
psiModifiers.add(PsiModifier.PUBLIC); // For internal (default) visibility
|
||||
}
|
||||
|
||||
|
||||
// FINAL
|
||||
if (isAbstract(classOrObject)) {
|
||||
psiModifiers.add(PsiModifier.ABSTRACT);
|
||||
}
|
||||
else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject instanceof JetClass && ((JetClass) classOrObject).isEnum()))) {
|
||||
psiModifiers.add(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) {
|
||||
psiModifiers.add(PsiModifier.STATIC);
|
||||
}
|
||||
|
||||
return ArrayUtil.toStringArray(psiModifiers);
|
||||
}
|
||||
|
||||
private boolean isAbstract(@NotNull JetClassOrObject object) {
|
||||
return object.hasModifier(ABSTRACT_KEYWORD) || isInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@NonNls @NotNull String name) {
|
||||
return getModifierList().hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
JetModifierList jetModifierList = classOrObject.getModifierList();
|
||||
if (jetModifierList == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassDescriptor deprecatedAnnotation = KotlinBuiltIns.getInstance().getDeprecatedAnnotation();
|
||||
String deprecatedName = deprecatedAnnotation.getName().asString();
|
||||
FqNameUnsafe deprecatedFqName = DescriptorUtils.getFqName(deprecatedAnnotation);
|
||||
|
||||
for (JetAnnotationEntry annotationEntry : jetModifierList.getAnnotationEntries()) {
|
||||
JetTypeReference typeReference = annotationEntry.getTypeReference();
|
||||
if (typeReference == null) continue;
|
||||
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
if (!(typeElement instanceof JetUserType)) continue; // If it's not a user type, it's definitely not a ref to deprecated
|
||||
|
||||
FqName fqName = JetPsiUtil.toQualifiedName((JetUserType) typeElement);
|
||||
if (fqName == null) continue;
|
||||
|
||||
if (deprecatedFqName.equals(fqName.toUnsafe())) return true;
|
||||
if (deprecatedName.equals(fqName.asString())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterface() {
|
||||
if (!(classOrObject instanceof JetClass)) return false;
|
||||
JetClass jetClass = (JetClass) classOrObject;
|
||||
return jetClass.isTrait() || jetClass.isAnnotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationType() {
|
||||
return classOrObject instanceof JetClass && ((JetClass) classOrObject).isAnnotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnum() {
|
||||
return classOrObject instanceof JetClass && ((JetClass) classOrObject).isEnum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTypeParameters() {
|
||||
return classOrObject instanceof JetClass && !((JetClass) classOrObject).getTypeParameters().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return classOrObject.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
|
||||
// Java inheritor check doesn't work when trait (interface in Java) subclasses Java class and for Kotlin local classes
|
||||
if (baseClass instanceof KotlinLightClassForExplicitDeclaration || (isInterface() && !baseClass.isInterface())) {
|
||||
String qualifiedName;
|
||||
if (baseClass instanceof KotlinLightClassForExplicitDeclaration) {
|
||||
ClassDescriptor baseDescriptor = ((KotlinLightClassForExplicitDeclaration) baseClass).getDescriptor();
|
||||
qualifiedName = baseDescriptor != null ? DescriptorUtils.getFqName(baseDescriptor).asString() : null;
|
||||
}
|
||||
else {
|
||||
qualifiedName = baseClass.getQualifiedName();
|
||||
}
|
||||
|
||||
ClassDescriptor thisDescriptor = getDescriptor();
|
||||
return qualifiedName != null
|
||||
&& thisDescriptor != null
|
||||
&& checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep);
|
||||
}
|
||||
|
||||
return super.isInheritor(baseClass, checkDeep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Cannot modify compiled kotlin element");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return KotlinLightClass.class.getSimpleName() + ":" + getQualifiedName();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return KotlinLightClass.class.getSimpleName() + ":" + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PsiClass> getOwnInnerClasses() {
|
||||
return KotlinPackage.filterNotNull(
|
||||
KotlinPackage.map(
|
||||
getDelegate().getInnerClasses(),
|
||||
new Function1<PsiClass, PsiClass>() {
|
||||
@Override
|
||||
public PsiClass invoke(PsiClass aClass) {
|
||||
JetClassOrObject declaration = (JetClassOrObject) ClsWrapperStubPsiFactory.getOriginalDeclaration(aClass);
|
||||
return declaration != null ? KotlinLightClassForExplicitDeclaration.create(myManager, declaration) : null;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean checkSuperTypeByFQName(@NotNull ClassDescriptor classDescriptor, @NotNull String qualifiedName, Boolean deep) {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) return true;
|
||||
|
||||
if (qualifiedName.equals(DescriptorUtils.getFqName(classDescriptor).asString())) return true;
|
||||
|
||||
for (JetType superType : classDescriptor.getTypeConstructor().getSupertypes()) {
|
||||
ClassifierDescriptor superDescriptor = superType.getConstructor().getDeclarationDescriptor();
|
||||
|
||||
if (superDescriptor instanceof ClassDescriptor) {
|
||||
if (qualifiedName.equals(DescriptorUtils.getFqName(superDescriptor).asString())) return true;
|
||||
|
||||
if (deep) {
|
||||
if (checkSuperTypeByFQName((ClassDescriptor)superDescriptor, qualifiedName, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightEmptyImplementsList;
|
||||
import com.intellij.psi.impl.light.LightModifierList;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class KotlinLightClassForPackage extends KotlinWrappingLightClass implements JetJavaMirrorMarker {
|
||||
|
||||
public static class FileStubCache {
|
||||
|
||||
@NotNull
|
||||
public static FileStubCache getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, FileStubCache.class);
|
||||
}
|
||||
|
||||
private static final class Key {
|
||||
private final FqName fqName;
|
||||
private final GlobalSearchScope searchScope;
|
||||
|
||||
private Key(
|
||||
@NotNull FqName fqName,
|
||||
@NotNull GlobalSearchScope searchScope
|
||||
) {
|
||||
this.fqName = fqName;
|
||||
this.searchScope = searchScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (!fqName.equals(key.fqName)) return false;
|
||||
if (!searchScope.equals(key.searchScope)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fqName.hashCode();
|
||||
result = 31 * result + searchScope.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final class CacheData {
|
||||
|
||||
private final SLRUCache<Key, CachedValue<KotlinPackageLightClassData>> cache = new SLRUCache<Key, CachedValue<KotlinPackageLightClassData>>(20, 30) {
|
||||
@NotNull
|
||||
@Override
|
||||
public CachedValue<KotlinPackageLightClassData> createValue(Key key) {
|
||||
KotlinJavaFileStubProvider<KotlinPackageLightClassData> stubProvider =
|
||||
KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope);
|
||||
return CachedValuesManager.getManager(project).createCachedValue(stubProvider, /*trackValue = */false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final Project project;
|
||||
private final CachedValue<CacheData> cachedValue;
|
||||
|
||||
public FileStubCache(@NotNull Project project) {
|
||||
this.project = project;
|
||||
this.cachedValue = CachedValuesManager.getManager(project).createCachedValue(
|
||||
new CachedValueProvider<CacheData>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<CacheData> compute() {
|
||||
return Result.create(new CacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
},
|
||||
/*trackValue = */ false
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CachedValue<KotlinPackageLightClassData> get(
|
||||
@NotNull FqName qualifiedName,
|
||||
@NotNull GlobalSearchScope searchScope
|
||||
) {
|
||||
synchronized (cachedValue) {
|
||||
return cachedValue.getValue().cache.get(new Key(qualifiedName, searchScope));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final FqName packageFqName;
|
||||
private final FqName packageClassFqName; // derived from packageFqName
|
||||
private final GlobalSearchScope searchScope;
|
||||
private final Collection<JetFile> files;
|
||||
private final int hashCode;
|
||||
private final CachedValue<KotlinPackageLightClassData> lightClassDataCache;
|
||||
private final PsiModifierList modifierList;
|
||||
private final LightEmptyImplementsList implementsList;
|
||||
|
||||
private KotlinLightClassForPackage(
|
||||
@NotNull PsiManager manager,
|
||||
@NotNull FqName packageFqName,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull Collection<JetFile> files
|
||||
) {
|
||||
super(manager);
|
||||
this.modifierList = new LightModifierList(manager, JetLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL);
|
||||
this.implementsList = new LightEmptyImplementsList(manager);
|
||||
this.packageFqName = packageFqName;
|
||||
this.packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||
this.searchScope = searchScope;
|
||||
assert !files.isEmpty() : "No files for package " + packageFqName;
|
||||
this.files = Sets.newHashSet(files); // needed for hashCode
|
||||
this.hashCode = computeHashCode();
|
||||
this.lightClassDataCache = FileStubCache.getInstance(getProject()).get(packageFqName, searchScope);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KotlinLightClassForPackage create(
|
||||
@NotNull PsiManager manager,
|
||||
@NotNull FqName qualifiedName,
|
||||
@NotNull GlobalSearchScope searchScope,
|
||||
@NotNull Collection<JetFile> files // this is redundant, but computing it multiple times is costly
|
||||
) {
|
||||
for (JetFile file : files) {
|
||||
if (LightClassUtil.belongsToKotlinBuiltIns(file)) return null;
|
||||
}
|
||||
return new KotlinLightClassForPackage(manager, qualifiedName, searchScope, files);
|
||||
}
|
||||
|
||||
private static boolean allValid(Collection<JetFile> files) {
|
||||
for (JetFile file : files) {
|
||||
if (!file.isValid()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JetClassOrObject getOrigin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return modifierList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@NonNls @NotNull String name) {
|
||||
return modifierList.hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterface() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnum() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTypeParameters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeParameter[] getTypeParameters() {
|
||||
return PsiTypeParameter.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiTypeParameterList getTypeParameterList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiDocComment getDocComment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiReferenceList getImplementsList() {
|
||||
return implementsList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getImplementsListTypes() {
|
||||
return PsiClassType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiReferenceList getExtendsList() {
|
||||
// TODO: Find a way to return just Object
|
||||
return super.getExtendsList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getExtendsListTypes() {
|
||||
// TODO see getExtendsList()
|
||||
return super.getExtendsListTypes();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getSuperClass() {
|
||||
// TODO see getExtendsList()
|
||||
return super.getSuperClass();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getSupers() {
|
||||
// TODO see getExtendsList()
|
||||
return super.getSupers();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getSuperTypes() {
|
||||
// TODO see getExtendsList()
|
||||
return super.getSuperTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass[] getInterfaces() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getInnerClasses() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PsiClass> getOwnInnerClasses() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getAllInnerClasses() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassInitializer[] getInitializers() {
|
||||
return PsiClassInitializer.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass findInnerClassByName(@NonNls String name, boolean checkBases) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FqName getFqName() {
|
||||
return packageClassFqName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return packageClassFqName.shortName().asString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getQualifiedName() {
|
||||
return packageClassFqName.asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return allValid(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new KotlinLightClassForPackage(getManager(), packageFqName, searchScope, files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass getDelegate() {
|
||||
PsiClass psiClass = LightClassUtil.findClass(packageClassFqName, lightClassDataCache.getValue().getJavaFileStub());
|
||||
if (psiClass == null) {
|
||||
throw new IllegalStateException("Package class was not found " + packageFqName);
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return files.iterator().next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
return another instanceof PsiClass && Comparing.equal(((PsiClass) another).getQualifiedName(), getQualifiedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getElementIcon(int flags) {
|
||||
throw new UnsupportedOperationException("This should be done byt JetIconProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private int computeHashCode() {
|
||||
int result = getManager().hashCode();
|
||||
result = 31 * result + files.hashCode();
|
||||
result = 31 * result + packageFqName.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
KotlinLightClassForPackage lightClass = (KotlinLightClassForPackage) obj;
|
||||
|
||||
if (this.hashCode != lightClass.hashCode) return false;
|
||||
if (getManager() != lightClass.getManager()) return false;
|
||||
if (!files.equals(lightClass.files)) return false;
|
||||
if (!packageFqName.equals(lightClass.packageFqName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return KotlinLightClassForPackage.class.getSimpleName() + ":" + getQualifiedName();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return KotlinLightClassForPackage.class.getSimpleName() + ":" + e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: this is only needed to compute plugin module info
|
||||
@NotNull
|
||||
@ReadOnly
|
||||
public final Collection<JetFile> getFiles() {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
public trait KotlinLightElement<T : JetDeclaration, D : PsiElement> {
|
||||
public val origin: T?
|
||||
public val delegate: D
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.jet.lang.psi.JetEnumEntry
|
||||
|
||||
class KotlinLightEnumConstant(
|
||||
manager: PsiManager,
|
||||
origin: JetEnumEntry,
|
||||
enumConstant: PsiEnumConstant,
|
||||
containingClass: PsiClass,
|
||||
private val initializingClass: PsiEnumConstantInitializer?
|
||||
) : KotlinLightField<JetEnumEntry, PsiEnumConstant>(manager, origin, enumConstant, containingClass), PsiEnumConstant {
|
||||
override fun copy() = KotlinLightEnumConstant(getManager()!!, getOrigin(), getDelegate(), getContainingClass()!!, initializingClass)
|
||||
|
||||
// NOTE: we don't use "delegation by" because the compiler would generate method calls to ALL of PsiEnumConstant members,
|
||||
// but we need only members whose implementations are not present in KotlinLightField
|
||||
override fun getArgumentList(): PsiExpressionList? = getDelegate().getArgumentList()
|
||||
override fun getInitializingClass(): PsiEnumConstantInitializer? = initializingClass
|
||||
override fun getOrCreateInitializingClass(): PsiEnumConstantInitializer =
|
||||
initializingClass ?: throw UnsupportedOperationException("Can't create enum constant body: ${getDelegate().getName()}")
|
||||
override fun resolveConstructor(): PsiMethod? = getDelegate().resolveConstructor()
|
||||
override fun resolveMethod(): PsiMethod? = getDelegate().resolveMethod()
|
||||
override fun resolveMethodGenerics(): JavaResolveResult = getDelegate().resolveMethodGenerics()
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
// Copied from com.intellij.psi.impl.light.LightField
|
||||
public abstract class KotlinLightField<T extends JetDeclaration, D extends PsiField> extends LightElement
|
||||
implements PsiField, KotlinLightElement<T, D> {
|
||||
private final T origin;
|
||||
private final D delegate;
|
||||
private final PsiClass containingClass;
|
||||
|
||||
public KotlinLightField(@NotNull PsiManager manager, @NotNull T origin, @NotNull D delegate, @NotNull PsiClass containingClass) {
|
||||
super(manager, JavaLanguage.INSTANCE);
|
||||
this.origin = origin;
|
||||
this.delegate = delegate;
|
||||
this.containingClass = containingClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract KotlinLightField<T, D> copy();
|
||||
|
||||
@Override
|
||||
public void setInitializer(@Nullable PsiExpression initializer) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SearchScope getUseScope() {
|
||||
return delegate.getUseScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return delegate.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiIdentifier getNameIdentifier() {
|
||||
return delegate.getNameIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiDocComment getDocComment() {
|
||||
return delegate.getDocComment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return delegate.isDeprecated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
return containingClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return delegate.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeElement getTypeElement() {
|
||||
return delegate.getTypeElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getInitializer() {
|
||||
return delegate.getInitializer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInitializer() {
|
||||
return delegate.hasInitializer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalizeDeclaration() throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object computeConstantValue() {
|
||||
return delegate.computeConstantValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return delegate.getModifierList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@NonNls @NotNull String name) {
|
||||
return delegate.hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return delegate.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange getTextRange() {
|
||||
return new TextRange(-1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return containingClass.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiField:" + getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public T getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public D getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return getOrigin();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return JetLanguage.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
|
||||
class KotlinLightFieldForDeclaration(
|
||||
manager: PsiManager,
|
||||
origin: JetDeclaration,
|
||||
field: PsiField,
|
||||
containingClass: PsiClass
|
||||
) : KotlinLightField<JetDeclaration, PsiField>(manager, origin, field, containingClass) {
|
||||
override fun copy() = KotlinLightFieldForDeclaration(getManager()!!, getOrigin(), getDelegate(), getContainingClass()!!)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
|
||||
public trait KotlinLightMethod: PsiMethod, KotlinLightElement<JetDeclaration, PsiMethod>
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.impl.light.LightMethod
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import org.jetbrains.jet.plugin.JetLanguage
|
||||
import kotlin.properties.Delegates
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.lang.Language
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import com.intellij.psi.util.MethodSignature
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
|
||||
|
||||
open public class KotlinLightMethodForDeclaration(
|
||||
manager: PsiManager,
|
||||
override val delegate: PsiMethod,
|
||||
override val origin: JetDeclaration,
|
||||
containingClass: PsiClass
|
||||
): LightMethod(manager, delegate, containingClass), KotlinLightMethod {
|
||||
|
||||
private val paramsList: CachedValue<PsiParameterList> by Delegates.blockingLazy {
|
||||
val cacheManager = CachedValuesManager.getManager(delegate.getProject())
|
||||
cacheManager.createCachedValue<PsiParameterList>({
|
||||
val parameterBuilder = LightParameterListBuilder(getManager(), JetLanguage.INSTANCE, this)
|
||||
|
||||
for ((index, parameter) in delegate.getParameterList().getParameters().withIndices()) {
|
||||
parameterBuilder.addParameter(KotlinLightParameter(parameter, index, this))
|
||||
}
|
||||
|
||||
CachedValueProvider.Result.create(parameterBuilder, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
|
||||
}, false)
|
||||
}
|
||||
|
||||
private val typeParamsList: CachedValue<PsiTypeParameterList> by Delegates.blockingLazy {
|
||||
val cacheManager = CachedValuesManager.getManager(delegate.getProject())
|
||||
cacheManager.createCachedValue<PsiTypeParameterList>({
|
||||
val list = if (origin is JetClassOrObject) {
|
||||
KotlinLightTypeParameterListBuilder(getManager())
|
||||
}
|
||||
else {
|
||||
LightClassUtil.buildLightTypeParameterList(this@KotlinLightMethodForDeclaration, origin)
|
||||
}
|
||||
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
|
||||
}, false)
|
||||
}
|
||||
|
||||
override fun getNavigationElement() : PsiElement = origin
|
||||
override fun getOriginalElement() : PsiElement = origin
|
||||
|
||||
override fun getParent(): PsiElement? = getContainingClass()
|
||||
|
||||
override fun setName(name: String): PsiElement? {
|
||||
(origin as PsiNamedElement).setName(name)
|
||||
return this
|
||||
}
|
||||
|
||||
public override fun delete() {
|
||||
if (origin.isValid()) {
|
||||
origin.delete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun isEquivalentTo(another: PsiElement?): Boolean {
|
||||
if (another is KotlinLightMethod && origin == another.origin) {
|
||||
return true
|
||||
}
|
||||
|
||||
return super<LightMethod>.isEquivalentTo(another)
|
||||
}
|
||||
|
||||
override fun getParameterList(): PsiParameterList = paramsList.getValue()!!
|
||||
|
||||
override fun getTypeParameterList(): PsiTypeParameterList? = typeParamsList.getValue()
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> =
|
||||
getTypeParameterList()?.let { it.getTypeParameters() } ?: PsiTypeParameter.EMPTY_ARRAY
|
||||
|
||||
override fun getSignature(substitutor: PsiSubstitutor): MethodSignature {
|
||||
if (substitutor == PsiSubstitutor.EMPTY) {
|
||||
return delegate.getSignature(substitutor)
|
||||
}
|
||||
return MethodSignatureBackedByPsiMethod.create(this, substitutor)
|
||||
}
|
||||
|
||||
override fun copy(): PsiElement {
|
||||
return KotlinLightMethodForDeclaration(getManager()!!, delegate, origin.copy() as JetDeclaration, getContainingClass()!!)
|
||||
}
|
||||
|
||||
override fun getUseScope(): SearchScope = origin.getUseScope()
|
||||
|
||||
override fun getLanguage(): Language = JetLanguage.INSTANCE
|
||||
|
||||
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
||||
return getTypeParameters().all { processor.execute(it, state) }
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KotlinLightMethodForDeclaration &&
|
||||
getName() == other.getName() &&
|
||||
origin == other.origin &&
|
||||
getContainingClass() == other.getContainingClass()
|
||||
|
||||
override fun hashCode(): Int = (getName().hashCode() * 31 + origin.hashCode()) * 31 + getContainingClass()!!.hashCode()
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||
import com.intellij.psi.PsiClass
|
||||
import org.jetbrains.jet.asJava.KotlinLightMethodForTraitFakeOverride
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
|
||||
public class KotlinLightMethodForTraitFakeOverride(manager: PsiManager,
|
||||
override val delegate: PsiMethod,
|
||||
override val origin: JetDeclaration,
|
||||
containingClass: PsiClass) :
|
||||
KotlinLightMethodForDeclaration(manager, delegate, origin, containingClass) {
|
||||
|
||||
override fun copy(): PsiElement {
|
||||
return KotlinLightMethodForTraitFakeOverride(getManager()!!, delegate, origin.copy() as JetDeclaration, getContainingClass()!!)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiAnnotationOwner;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.light.LightModifierList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
public abstract class KotlinLightModifierList extends LightModifierList {
|
||||
public KotlinLightModifierList(PsiManager psiManager, @NotNull String[] modifiers) {
|
||||
super(psiManager, JetLanguage.INSTANCE, modifiers);
|
||||
}
|
||||
|
||||
public abstract PsiAnnotationOwner getDelegate();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiAnnotation[] getAnnotations() {
|
||||
return getDelegate().getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiAnnotation[] getApplicableAnnotations() {
|
||||
return getDelegate().getApplicableAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
|
||||
return getDelegate().findAnnotation(qualifiedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
|
||||
return getDelegate().addAnnotation(qualifiedName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.PsiAnnotationOwner;
|
||||
import com.intellij.psi.PsiModifierList;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KotlinLightParameter extends LightParameter implements KotlinLightElement<JetParameter, PsiParameter> {
|
||||
private static String getName(PsiParameter delegate, int index) {
|
||||
String name = delegate.getName();
|
||||
return name != null ? name : "p" + index;
|
||||
}
|
||||
|
||||
private final PsiModifierList modifierList;
|
||||
private final PsiParameter delegate;
|
||||
private final int index;
|
||||
private final KotlinLightMethod method;
|
||||
|
||||
public KotlinLightParameter(final PsiParameter delegate, int index, KotlinLightMethod method) {
|
||||
super(getName(delegate, index), delegate.getType(), method, JetLanguage.INSTANCE);
|
||||
|
||||
this.delegate = delegate;
|
||||
this.index = index;
|
||||
this.method = method;
|
||||
|
||||
this.modifierList = new KotlinLightModifierList(method.getManager(), ArrayUtil.EMPTY_STRING_ARRAY) {
|
||||
@Override
|
||||
public PsiAnnotationOwner getDelegate() {
|
||||
return delegate.getModifierList();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return modifierList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiParameter getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JetParameter getOrigin() {
|
||||
JetDeclaration declaration = method.getOrigin();
|
||||
if (declaration == null) return null;
|
||||
|
||||
int jetIndex = PsiUtilPackage.isExtensionDeclaration(declaration) ? index - 1 : index;
|
||||
if (jetIndex < 0) return null;
|
||||
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
List<JetParameter> paramList = ((JetNamedFunction) declaration).getValueParameters();
|
||||
return jetIndex < paramList.size() ? paramList.get(jetIndex) : null;
|
||||
}
|
||||
|
||||
if (declaration instanceof JetClass) {
|
||||
List<JetParameter> paramList = ((JetClass) declaration).getPrimaryConstructorParameters();
|
||||
return jetIndex < paramList.size() ? paramList.get(jetIndex) : null;
|
||||
}
|
||||
|
||||
if (jetIndex != 0) return null;
|
||||
|
||||
JetPropertyAccessor setter = null;
|
||||
if (declaration instanceof JetPropertyAccessor) {
|
||||
JetPropertyAccessor accessor = (JetPropertyAccessor) declaration;
|
||||
setter = accessor.isSetter() ? accessor : null;
|
||||
}
|
||||
else if (declaration instanceof JetProperty) {
|
||||
setter = ((JetProperty) declaration).getSetter();
|
||||
}
|
||||
|
||||
return setter != null ? setter.getParameter() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return JetLanguage.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.AbstractLightClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeParameter;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
public class KotlinLightTypeParameter
|
||||
extends AbstractLightClass implements PsiTypeParameter, KotlinLightElement<JetTypeParameter, PsiTypeParameter> {
|
||||
private final PsiTypeParameterListOwner owner;
|
||||
private final int index;
|
||||
private final String name;
|
||||
|
||||
protected KotlinLightTypeParameter(
|
||||
@NotNull PsiTypeParameterListOwner owner,
|
||||
int index,
|
||||
@NotNull String name) {
|
||||
super(owner.getManager(), JetLanguage.INSTANCE);
|
||||
this.owner = owner;
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeParameter getDelegate() {
|
||||
return getOwnerDelegate().getTypeParameters()[index];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetTypeParameter getOrigin() {
|
||||
JetTypeParameterListOwner jetOwner = (JetTypeParameterListOwner) AsJavaPackage.getUnwrapped(owner);
|
||||
assert (jetOwner != null) : "Invalid type parameter owner: " + owner;
|
||||
|
||||
return jetOwner.getTypeParameters().get(index);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiTypeParameterListOwner getOwnerDelegate() {
|
||||
if (owner instanceof KotlinLightClass) return ((KotlinLightClass) owner).getDelegate();
|
||||
if (owner instanceof KotlinLightMethod) return ((KotlinLightMethod) owner).getDelegate();
|
||||
return owner;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new KotlinLightTypeParameter(owner, index, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor) visitor).visitTypeParameter(this);
|
||||
}
|
||||
else {
|
||||
super.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeParameterListOwner getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation[] getAnnotations() {
|
||||
return getDelegate().getAnnotations();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation[] getApplicableAnnotations() {
|
||||
return getDelegate().getApplicableAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiAnnotation findAnnotation(@NotNull String qualifiedName) {
|
||||
return getDelegate().findAnnotation(qualifiedName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation addAnnotation(@NotNull String qualifiedName) {
|
||||
return getDelegate().addAnnotation(qualifiedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KotlinLightTypeParameter:" + getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return getOrigin();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return JetLanguage.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof KotlinLightTypeParameter && getOrigin().equals(((KotlinLightTypeParameter) obj).getOrigin());
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.jet.plugin.JetLanguage
|
||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import com.intellij.psi.ResolveState
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
public class KotlinLightTypeParameterListBuilder(manager: PsiManager): LightTypeParameterListBuilder(manager, JetLanguage.INSTANCE) {
|
||||
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
||||
return getTypeParameters().all { processor.execute(it, state) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.light.AbstractLightClass;
|
||||
import com.intellij.psi.impl.light.LightField;
|
||||
import com.intellij.psi.impl.light.LightMethod;
|
||||
import com.intellij.psi.impl.source.ClassInnerStuffCache;
|
||||
import com.intellij.psi.impl.source.PsiExtensibleClass;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class KotlinWrappingLightClass extends AbstractLightClass implements KotlinLightClass, PsiExtensibleClass {
|
||||
private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
|
||||
|
||||
protected KotlinWrappingLightClass(PsiManager manager) {
|
||||
super(manager, JetLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract PsiClass getDelegate();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiField[] getFields() {
|
||||
return myInnersCache.getFields();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiMethod[] getMethods() {
|
||||
return myInnersCache.getMethods();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiMethod[] getConstructors() {
|
||||
return myInnersCache.getConstructors();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiClass[] getInnerClasses() {
|
||||
return myInnersCache.getInnerClasses();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiField[] getAllFields() {
|
||||
return PsiClassImplUtil.getAllFields(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiMethod[] getAllMethods() {
|
||||
return PsiClassImplUtil.getAllMethods(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiClass[] getAllInnerClasses() {
|
||||
return PsiClassImplUtil.getAllInnerClasses(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiField findFieldByName(String name, boolean checkBases) {
|
||||
return myInnersCache.findFieldByName(name, checkBases);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
|
||||
return myInnersCache.findMethodsByName(name, checkBases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass findInnerClassByName(String name, boolean checkBases) {
|
||||
return myInnersCache.findInnerClassByName(name, checkBases);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.jet.codegen.binding.CodegenBinding#ENUM_ENTRY_CLASS_NEED_SUBCLASS
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PsiField> getOwnFields() {
|
||||
return ContainerUtil.map(getDelegate().getFields(), new Function<PsiField, PsiField>() {
|
||||
@Override
|
||||
public PsiField fun(PsiField field) {
|
||||
JetDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(field);
|
||||
if (declaration instanceof JetEnumEntry) {
|
||||
assert field instanceof PsiEnumConstant : "Field delegate should be an enum constant (" + field.getName() + "):\n" +
|
||||
JetPsiUtil.getElementTextWithContext(declaration);
|
||||
JetEnumEntry enumEntry = (JetEnumEntry) declaration;
|
||||
PsiEnumConstant enumConstant = (PsiEnumConstant) field;
|
||||
FqName enumConstantFqName = new FqName(getFqName().asString() + "." + enumEntry.getName());
|
||||
KotlinLightClassForEnumEntry initializingClass =
|
||||
enumEntry.getDeclarations().isEmpty()
|
||||
? null
|
||||
: new KotlinLightClassForEnumEntry(myManager, enumConstantFqName, enumEntry, enumConstant);
|
||||
return new KotlinLightEnumConstant(myManager, enumEntry, enumConstant, KotlinWrappingLightClass.this, initializingClass);
|
||||
}
|
||||
if (declaration != null) {
|
||||
return new KotlinLightFieldForDeclaration(myManager, declaration, field, KotlinWrappingLightClass.this);
|
||||
}
|
||||
return new LightField(myManager, field, KotlinWrappingLightClass.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PsiMethod> getOwnMethods() {
|
||||
return KotlinPackage.map(getDelegate().getMethods(), new Function1<PsiMethod, PsiMethod>() {
|
||||
@Override
|
||||
public PsiMethod invoke(PsiMethod method) {
|
||||
JetDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(method);
|
||||
|
||||
if (declaration != null) {
|
||||
return !isTraitFakeOverride(declaration) ?
|
||||
new KotlinLightMethodForDeclaration(myManager, method, declaration, KotlinWrappingLightClass.this) :
|
||||
new KotlinLightMethodForTraitFakeOverride(myManager, method, declaration, KotlinWrappingLightClass.this);
|
||||
}
|
||||
|
||||
return new LightMethod(myManager, method, KotlinWrappingLightClass.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDeclarations(
|
||||
@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place
|
||||
) {
|
||||
if (isEnum()) {
|
||||
if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false;
|
||||
}
|
||||
|
||||
return super.processDeclarations(processor, state, lastParent, place);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
JetClassOrObject origin = getOrigin();
|
||||
return origin == null ? null : origin.getText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return JetLanguage.INSTANCE;
|
||||
}
|
||||
|
||||
private boolean isTraitFakeOverride(@NotNull JetDeclaration originMethodDeclaration) {
|
||||
if (!(originMethodDeclaration instanceof JetNamedFunction ||
|
||||
originMethodDeclaration instanceof JetPropertyAccessor ||
|
||||
originMethodDeclaration instanceof JetProperty)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JetClassOrObject parentOfMethodOrigin = PsiTreeUtil.getParentOfType(originMethodDeclaration, JetClassOrObject.class);
|
||||
JetClassOrObject thisClassDeclaration = getOrigin();
|
||||
|
||||
// Method was generated from declaration in some other trait
|
||||
return (parentOfMethodOrigin != null && thisClassDeclaration != parentOfMethodOrigin && JetPsiUtil.isTrait(parentOfMethodOrigin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
public class LightClassConstructionContext {
|
||||
private final BindingContext bindingContext;
|
||||
private final ModuleDescriptor module;
|
||||
|
||||
public LightClassConstructionContext(@NotNull BindingContext bindingContext, @NotNull ModuleDescriptor module) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BindingContext getBindingContext() {
|
||||
return bindingContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ModuleDescriptor getModule() {
|
||||
return module;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class LightClassGenerationSupport {
|
||||
|
||||
@NotNull
|
||||
public static LightClassGenerationSupport getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, LightClassGenerationSupport.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract LightClassConstructionContext getContextForPackage(@NotNull Collection<JetFile> files);
|
||||
|
||||
@NotNull
|
||||
public abstract LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject);
|
||||
|
||||
@NotNull
|
||||
public abstract Collection<JetClassOrObject> findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope);
|
||||
|
||||
/*
|
||||
* Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares
|
||||
* package a.b.c
|
||||
* it will not be returned for fqName "a.b"
|
||||
*
|
||||
* If the resulting collection is empty, it means that this package has not other declarations than sub-packages
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Collection<JetFile> findFilesForPackage(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope);
|
||||
|
||||
// Returns only immediately declared classes/objects, package classes are not included (they have no declarations)
|
||||
@NotNull
|
||||
public abstract Collection<JetClassOrObject> findClassOrObjectDeclarationsInPackage(
|
||||
@NotNull FqName packageFqName,
|
||||
@NotNull GlobalSearchScope searchScope
|
||||
);
|
||||
|
||||
public abstract boolean packageExists(@NotNull FqName fqName, @NotNull GlobalSearchScope scope);
|
||||
|
||||
@NotNull
|
||||
public abstract Collection<FqName> getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiClass getPsiClass(@NotNull JetClassOrObject classOrObject);
|
||||
|
||||
@NotNull
|
||||
public abstract Collection<PsiClass> getPackageClasses(@NotNull FqName packageFqName, @NotNull GlobalSearchScope scope);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
import org.jetbrains.jet.lang.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||
|
||||
trait LightClassData
|
||||
|
||||
trait WithFileStubAndExtraDiagnostics {
|
||||
val javaFileStub: PsiJavaFileStub
|
||||
val extraDiagnostics: Diagnostics
|
||||
}
|
||||
|
||||
trait LightClassDataForKotlinClass: LightClassData {
|
||||
val classOrObject: JetClassOrObject
|
||||
val descriptor: ClassDescriptor?
|
||||
val jvmQualifiedName: FqName
|
||||
}
|
||||
|
||||
data class KotlinPackageLightClassData(
|
||||
override val javaFileStub: PsiJavaFileStub,
|
||||
override val extraDiagnostics: Diagnostics
|
||||
): LightClassData, WithFileStubAndExtraDiagnostics
|
||||
|
||||
data class InnerKotlinClassLightClassData(
|
||||
override val jvmQualifiedName: FqName,
|
||||
override val classOrObject: JetClassOrObject,
|
||||
override val descriptor: ClassDescriptor?
|
||||
): LightClassDataForKotlinClass
|
||||
|
||||
data class OutermostKotlinClassLightClassData(
|
||||
override val javaFileStub: PsiJavaFileStub,
|
||||
override val extraDiagnostics: Diagnostics,
|
||||
override val jvmQualifiedName: FqName,
|
||||
override val classOrObject: JetClassOrObject,
|
||||
override val descriptor: ClassDescriptor?,
|
||||
val allInnerClasses: Map<JetClassOrObject, InnerKotlinClassLightClassData>
|
||||
): LightClassDataForKotlinClass, WithFileStubAndExtraDiagnostics
|
||||
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassStub;
|
||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.utils.KotlinVfsUtil;
|
||||
import org.jetbrains.jet.utils.UtilsPackage;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
public class LightClassUtil {
|
||||
private static final Logger LOG = Logger.getInstance(LightClassUtil.class);
|
||||
|
||||
public static final File BUILT_INS_SRC_DIR = new File("core/builtins/native", KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString());
|
||||
|
||||
private static final class BuiltinsDirUrlHolder {
|
||||
private static final URL BUILT_INS_DIR_URL = computeBuiltInsDir();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given file is loaded from the location where Kotlin's built-in classes are defined.
|
||||
* As of today, this is core/builtins/native/kotlin directory and files such as Any.kt, Nothing.kt etc.
|
||||
*
|
||||
* Used to skip JetLightClass creation for built-ins, because built-in classes have no Java counterparts
|
||||
*/
|
||||
public static boolean belongsToKotlinBuiltIns(@NotNull JetFile file) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
VirtualFile parent = virtualFile.getParent();
|
||||
if (parent != null) {
|
||||
try {
|
||||
String jetVfsPathUrl = KotlinVfsUtil.convertFromUrl(getBuiltInsDirUrl());
|
||||
String fileDirVfsUrl = parent.getUrl();
|
||||
if (jetVfsPathUrl.equals(fileDirVfsUrl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We deliberately return false on error: who knows what weird URLs we might come across out there
|
||||
// it would be a pity if no light classes would be created in such cases
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static URL getBuiltInsDirUrl() {
|
||||
return BuiltinsDirUrlHolder.BUILT_INS_DIR_URL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static URL computeBuiltInsDir() {
|
||||
String builtInFilePath = "/" + KotlinBuiltIns.BUILT_INS_PACKAGE_NAME + "/Library.kt";
|
||||
|
||||
URL url = KotlinBuiltIns.class.getResource(builtInFilePath);
|
||||
|
||||
if (url == null) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// HACK: Temp code. Get built-in files from the sources when running from test.
|
||||
try {
|
||||
return new URL(StandardFileSystems.FILE_PROTOCOL, "",
|
||||
FileUtil.toSystemIndependentName(BUILT_INS_SRC_DIR.getAbsolutePath()));
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Built-ins file wasn't found at url: " + builtInFilePath);
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), PathUtil.getParentPath(url.getFile()));
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
/*package*/ static PsiClass findClass(@NotNull FqName fqn, @NotNull StubElement<?> stub) {
|
||||
if (stub instanceof PsiClassStub && Comparing.equal(fqn.asString(), ((PsiClassStub) stub).getQualifiedName())) {
|
||||
return (PsiClass) stub.getPsi();
|
||||
}
|
||||
|
||||
if (stub instanceof PsiClassStub || stub instanceof PsiFileStub) {
|
||||
for (StubElement child : stub.getChildrenStubs()) {
|
||||
PsiClass answer = findClass(fqn, child);
|
||||
if (answer != null) return answer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getPsiClass(@Nullable JetClassOrObject classOrObject) {
|
||||
if (classOrObject == null) return null;
|
||||
return LightClassGenerationSupport.getInstance(classOrObject.getProject()).getPsiClass(classOrObject);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getLightClassAccessorMethod(@NotNull JetPropertyAccessor accessor) {
|
||||
return getPsiMethodWrapper(accessor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PropertyAccessorsPsiMethods getLightClassPropertyMethods(@NotNull JetProperty property) {
|
||||
JetPropertyAccessor getter = property.getGetter();
|
||||
JetPropertyAccessor setter = property.getSetter();
|
||||
|
||||
PsiMethod getterWrapper = getter != null ? getLightClassAccessorMethod(getter) : null;
|
||||
PsiMethod setterWrapper = setter != null ? getLightClassAccessorMethod(setter) : null;
|
||||
|
||||
return extractPropertyAccessors(property, getterWrapper, setterWrapper);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PropertyAccessorsPsiMethods getLightClassPropertyMethods(@NotNull JetParameter parameter) {
|
||||
return extractPropertyAccessors(parameter, null, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getLightClassMethod(@NotNull JetNamedFunction function) {
|
||||
return getPsiMethodWrapper(function);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiMethod getPsiMethodWrapper(@NotNull JetDeclaration declaration) {
|
||||
List<PsiMethod> wrappers = getPsiMethodWrappers(declaration, false);
|
||||
return !wrappers.isEmpty() ? wrappers.get(0) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PsiMethod> getPsiMethodWrappers(@NotNull JetDeclaration declaration, boolean collectAll) {
|
||||
PsiClass psiClass = getWrappingClass(declaration);
|
||||
if (psiClass == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<PsiMethod> methods = new SmartList<PsiMethod>();
|
||||
for (PsiMethod method : psiClass.getMethods()) {
|
||||
try {
|
||||
if (method instanceof KotlinLightMethod && ((KotlinLightMethod) method).getOrigin() == declaration) {
|
||||
methods.add(method);
|
||||
if (!collectAll) {
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new IllegalStateException(
|
||||
"Error while wrapping declaration " + declaration.getName() +
|
||||
"Context\n:" +
|
||||
String.format("=== In file ===\n" +
|
||||
"%s\n" +
|
||||
"=== On element ===\n" +
|
||||
"%s\n" +
|
||||
"=== WrappedElement ===\n" +
|
||||
"%s\n",
|
||||
declaration.getContainingFile().getText(),
|
||||
declaration.getText(),
|
||||
method.toString()),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getWrappingClass(@NotNull JetDeclaration declaration) {
|
||||
if (declaration instanceof JetParameter) {
|
||||
JetClass constructorClass = JetPsiUtil.getClassIfParameterIsProperty((JetParameter) declaration);
|
||||
if (constructorClass != null) {
|
||||
return getPsiClass(constructorClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration instanceof JetPropertyAccessor) {
|
||||
PsiElement propertyParent = declaration.getParent();
|
||||
assert propertyParent instanceof JetProperty : "JetProperty is expected to be parent of accessor";
|
||||
|
||||
declaration = (JetProperty) propertyParent;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
if (PsiTreeUtil.getParentOfType(declaration, JetFunction.class, JetProperty.class) != null) {
|
||||
// Can't get wrappers for internal declarations. Their classes are not generated during calcStub
|
||||
// with ClassBuilderMode.LIGHT_CLASSES mode, and this produces "Class not found exception" in getDelegate()
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiElement parent = declaration.getParent();
|
||||
|
||||
if (parent instanceof JetFile) {
|
||||
// top-level declaration
|
||||
FqName fqName = PackageClassUtils.getPackageClassFqName(((JetFile) parent).getPackageFqName());
|
||||
Project project = declaration.getProject();
|
||||
return JavaElementFinder.getInstance(project).findClass(fqName.asString(), GlobalSearchScope.allScope(project));
|
||||
}
|
||||
else if (parent instanceof JetClassBody) {
|
||||
assert parent.getParent() instanceof JetClassOrObject;
|
||||
return getPsiClass((JetClassOrObject) parent.getParent());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PropertyAccessorsPsiMethods extractPropertyAccessors(
|
||||
@NotNull JetDeclaration jetDeclaration,
|
||||
@Nullable PsiMethod specialGetter, @Nullable PsiMethod specialSetter
|
||||
) {
|
||||
PsiMethod getterWrapper = specialGetter;
|
||||
PsiMethod setterWrapper = specialSetter;
|
||||
|
||||
if (getterWrapper == null || setterWrapper == null) {
|
||||
// If some getter or setter isn't found yet try to get it from wrappers for general declaration
|
||||
|
||||
List<PsiMethod> wrappers = KotlinPackage.filter(
|
||||
getPsiMethodWrappers(jetDeclaration, true),
|
||||
new Function1<PsiMethod, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(PsiMethod method) {
|
||||
return JvmAbi.isAccessorName(method.getName());
|
||||
}
|
||||
}
|
||||
);
|
||||
assert wrappers.size() <= 2 : "Maximum two wrappers are expected to be generated for declaration: " + jetDeclaration.getText();
|
||||
|
||||
for (PsiMethod wrapper : wrappers) {
|
||||
if (wrapper.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
|
||||
assert setterWrapper == null : String.format(
|
||||
"Setter accessor isn't expected to be reassigned (old: %s, new: %s)", setterWrapper, wrapper);
|
||||
|
||||
setterWrapper = wrapper;
|
||||
}
|
||||
else {
|
||||
assert getterWrapper == null : String.format(
|
||||
"Getter accessor isn't expected to be reassigned (old: %s, new: %s)", getterWrapper, wrapper);
|
||||
|
||||
getterWrapper = wrapper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new PropertyAccessorsPsiMethods(getterWrapper, setterWrapper);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiTypeParameterList buildLightTypeParameterList(
|
||||
PsiTypeParameterListOwner owner,
|
||||
JetDeclaration declaration) {
|
||||
LightTypeParameterListBuilder builder = new KotlinLightTypeParameterListBuilder(owner.getManager());
|
||||
if (declaration instanceof JetTypeParameterListOwner) {
|
||||
JetTypeParameterListOwner typeParameterListOwner = (JetTypeParameterListOwner) declaration;
|
||||
List<JetTypeParameter> parameters = typeParameterListOwner.getTypeParameters();
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
JetTypeParameter jetTypeParameter = parameters.get(i);
|
||||
String name = jetTypeParameter.getName();
|
||||
String safeName = name == null ? "__no_name__" : name;
|
||||
builder.addParameter(new KotlinLightTypeParameter(owner, i, safeName));
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static class PropertyAccessorsPsiMethods implements Iterable<PsiMethod> {
|
||||
private final PsiMethod getter;
|
||||
private final PsiMethod setter;
|
||||
private final Collection<PsiMethod> accessors = new ArrayList<PsiMethod>(2);
|
||||
|
||||
PropertyAccessorsPsiMethods(@Nullable PsiMethod getter, @Nullable PsiMethod setter) {
|
||||
this.getter = getter;
|
||||
if (getter != null) {
|
||||
accessors.add(getter);
|
||||
}
|
||||
|
||||
this.setter = setter;
|
||||
if (setter != null) {
|
||||
accessors.add(setter);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiMethod getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiMethod getSetter() {
|
||||
return setter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<PsiMethod> iterator() {
|
||||
return accessors.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
private LightClassUtil() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// Based on com.intellij.psi.impl.light.LightParameter
|
||||
public class LightParameter extends LightVariableBuilder implements PsiParameter {
|
||||
public static final LightParameter[] EMPTY_ARRAY = new LightParameter[0];
|
||||
|
||||
private final String myName;
|
||||
private final PsiElement myDeclarationScope;
|
||||
private final boolean myVarArgs;
|
||||
|
||||
public LightParameter(@NotNull String name, @NotNull PsiType type, PsiElement declarationScope, Language language) {
|
||||
this(name, type, declarationScope, language, type instanceof PsiEllipsisType);
|
||||
}
|
||||
|
||||
public LightParameter(@NotNull String name, @NotNull PsiType type, PsiElement declarationScope, Language language, boolean isVarArgs) {
|
||||
super(declarationScope.getManager(), name, type, language);
|
||||
myName = name;
|
||||
myDeclarationScope = declarationScope;
|
||||
myVarArgs = isVarArgs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getDeclarationScope() {
|
||||
return myDeclarationScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor)visitor).visitParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Light Parameter";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVarArgs() {
|
||||
return myVarArgs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// Copy of com.intellij.psi.impl.light.LightParameterListBuilder
|
||||
public class LightParameterListBuilder extends LightElement implements PsiParameterList {
|
||||
private final List<PsiParameter> myParameters = new ArrayList<PsiParameter>();
|
||||
private final KotlinLightMethod parent;
|
||||
private PsiParameter[] myCachedParameters;
|
||||
|
||||
public LightParameterListBuilder(PsiManager manager, Language language, KotlinLightMethod parent) {
|
||||
super(manager, language);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void addParameter(PsiParameter parameter) {
|
||||
myParameters.add(parameter);
|
||||
myCachedParameters = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KotlinLightMethod getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Light parameter lsit";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiParameter[] getParameters() {
|
||||
if (myCachedParameters == null) {
|
||||
if (myParameters.isEmpty()) {
|
||||
myCachedParameters = PsiParameter.EMPTY_ARRAY;
|
||||
}
|
||||
else {
|
||||
myCachedParameters = myParameters.toArray(new PsiParameter[myParameters.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
return myCachedParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameterIndex(PsiParameter parameter) {
|
||||
return myParameters.indexOf(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParametersCount() {
|
||||
return myParameters.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof JavaElementVisitor) {
|
||||
((JavaElementVisitor) visitor).visitParameterList(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.ElementPresentationUtil;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.impl.light.LightModifierList;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
// Based on com.intellij.psi.impl.light.LightVariableBuilder
|
||||
public class LightVariableBuilder extends LightElement implements PsiVariable, NavigationItem {
|
||||
private final String myName;
|
||||
private final PsiType myType;
|
||||
private final LightModifierList myModifierList;
|
||||
|
||||
public LightVariableBuilder(PsiManager manager, @NotNull String name, @NotNull PsiType type, Language language) {
|
||||
super(manager, language);
|
||||
myName = name;
|
||||
myType = type;
|
||||
myModifierList = new LightModifierList(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LightVariableBuilder:" + getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiModifierList getModifierList() {
|
||||
return myModifierList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@NonNls @NotNull String name) {
|
||||
return myModifierList.hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeElement getTypeElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInitializer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalizeDeclaration() throws IncorrectOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object computeConstantValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiIdentifier getNameIdentifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("setName is not implemented yet in org.jetbrains.jet.asJava.light.LightVariableBuilder");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisibilitySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getElementIcon(int flags) {
|
||||
RowIcon baseIcon = ElementPresentationUtil.createLayeredIcon(PlatformIcons.VARIABLE_ICON, this, false);
|
||||
return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.asJava;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.compiled.InnerClassSourceStrategy;
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.jet.codegen.AbstractClassBuilder;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StubClassBuilder extends AbstractClassBuilder {
|
||||
private static final InnerClassSourceStrategy<Object> EMPTY_STRATEGY = new InnerClassSourceStrategy<Object>() {
|
||||
@Override
|
||||
public Object findInnerClass(String s, Object o) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Object innerClass, StubBuildingVisitor<Object> visitor) {
|
||||
throw new UnsupportedOperationException("Shall not be called!");
|
||||
}
|
||||
};
|
||||
private final StubElement parent;
|
||||
private StubBuildingVisitor v;
|
||||
private final Stack<StubElement> parentStack;
|
||||
private boolean isPackageClass = false;
|
||||
|
||||
public StubClassBuilder(@NotNull Stack<StubElement> parentStack) {
|
||||
this.parentStack = parentStack;
|
||||
this.parent = parentStack.peek();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassVisitor getVisitor() {
|
||||
assert v != null : "Called before class is defined";
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
assert v == null : "defineClass() called twice?";
|
||||
v = new StubBuildingVisitor<Object>(null, EMPTY_STRATEGY, parent, access, null);
|
||||
|
||||
super.defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
|
||||
if (origin instanceof JetFile) {
|
||||
FqName packageName = ((JetFile) origin).getPackageFqName();
|
||||
String packageClassName = PackageClassUtils.getPackageClassName(packageName);
|
||||
|
||||
if (name.equals(packageClassName) || name.endsWith("/" + packageClassName)) {
|
||||
isPackageClass = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isPackageClass) {
|
||||
parentStack.push(v.getResult());
|
||||
}
|
||||
|
||||
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
MethodVisitor internalVisitor = super.newMethod(origin, access, name, desc, signature, exceptions);
|
||||
|
||||
if (internalVisitor != EMPTY_METHOD_VISITOR) {
|
||||
// If stub for method generated
|
||||
markLastChild(origin.getElement());
|
||||
}
|
||||
|
||||
return internalVisitor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
FieldVisitor internalVisitor = super.newField(origin, access, name, desc, signature, value);
|
||||
|
||||
if (internalVisitor != EMPTY_FIELD_VISITOR) {
|
||||
// If stub for field generated
|
||||
markLastChild(origin.getElement());
|
||||
}
|
||||
|
||||
return internalVisitor;
|
||||
}
|
||||
|
||||
private void markLastChild(@Nullable PsiElement origin) {
|
||||
List children = v.getResult().getChildrenStubs();
|
||||
StubBase last = (StubBase) children.get(children.size() - 1);
|
||||
|
||||
PsiElement oldOrigin = last.getUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT);
|
||||
if (oldOrigin != null) {
|
||||
throw new IllegalStateException("Rewriting origin element: " + oldOrigin.getText() + " for stub " + last.toString());
|
||||
}
|
||||
|
||||
last.putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
if (!isPackageClass) {
|
||||
StubElement pop = parentStack.pop();
|
||||
assert pop == v.getResult();
|
||||
}
|
||||
super.done();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.lang.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.lang.psi.JetClassBody
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.ErrorsJvm.*
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.ConflictingJvmDeclarationsData
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOriginKind.*
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors.*
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory.*
|
||||
import org.jetbrains.jet.lang.psi.JetParameter
|
||||
import org.jetbrains.jet.lang.psi.JetClass
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
|
||||
|
||||
public fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? {
|
||||
fun getDiagnosticsForPackage(file: JetFile): Diagnostics? {
|
||||
val project = file.getProject()
|
||||
val cache = KotlinLightClassForPackage.FileStubCache.getInstance(project)
|
||||
return cache[file.getPackageFqName(), moduleScope].getValue()?.extraDiagnostics
|
||||
}
|
||||
|
||||
fun getDiagnosticsForClass(jetClassOrObject: JetClassOrObject): Diagnostics {
|
||||
return KotlinLightClassForExplicitDeclaration.getLightClassData(jetClassOrObject).extraDiagnostics
|
||||
}
|
||||
|
||||
fun doGetDiagnostics(): Diagnostics? {
|
||||
var parent = element.getParent()
|
||||
if (element is JetPropertyAccessor) {
|
||||
parent = parent?.getParent()
|
||||
}
|
||||
if (element is JetParameter && element.getValOrVarNode() != null) {
|
||||
// property declared in constructor
|
||||
val parentClass = parent?.getParent() as? JetClass
|
||||
if (parentClass != null) {
|
||||
return getDiagnosticsForClass(parentClass)
|
||||
}
|
||||
}
|
||||
if (element is JetClassOrObject) {
|
||||
return getDiagnosticsForClass(element)
|
||||
}
|
||||
|
||||
when (parent) {
|
||||
is JetFile -> {
|
||||
return getDiagnosticsForPackage(parent as JetFile)
|
||||
}
|
||||
is JetClassBody -> {
|
||||
val parentsParent = parent?.getParent()
|
||||
|
||||
if (parentsParent is JetClassOrObject) {
|
||||
return getDiagnosticsForClass(parentsParent)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val result = doGetDiagnostics()
|
||||
if (result == null) return null
|
||||
|
||||
return FilteredJvmDiagnostics(result, otherDiagnostics)
|
||||
}
|
||||
|
||||
class FilteredJvmDiagnostics(val jvmDiagnostics: Diagnostics, val otherDiagnostics: Diagnostics) : Diagnostics by jvmDiagnostics {
|
||||
|
||||
private fun alreadyReported(psiElement: PsiElement): Boolean {
|
||||
val higherPriority = setOf<DiagnosticFactory<*>>(
|
||||
CONFLICTING_OVERLOADS, REDECLARATION, NOTHING_TO_OVERRIDE, MANY_IMPL_MEMBER_NOT_IMPLEMENTED)
|
||||
return otherDiagnostics.forElement(psiElement).any { it.getFactory() in higherPriority }
|
||||
|| psiElement is JetPropertyAccessor && alreadyReported(psiElement.getParent()!!)
|
||||
}
|
||||
|
||||
override fun forElement(psiElement: PsiElement): Collection<Diagnostic> {
|
||||
val jvmDiagnosticFactories = setOf(CONFLICTING_JVM_DECLARATIONS, ACCIDENTAL_OVERRIDE)
|
||||
fun Diagnostic.data() = cast(this, jvmDiagnosticFactories).getA()
|
||||
val (conflicting, other) = jvmDiagnostics.forElement(psiElement).partition { it.getFactory() in jvmDiagnosticFactories }
|
||||
if (alreadyReported(psiElement)) {
|
||||
// CONFLICTING_OVERLOADS already reported, no need to duplicate it
|
||||
return other
|
||||
}
|
||||
|
||||
val filtered = arrayListOf<Diagnostic>()
|
||||
conflicting.groupBy {
|
||||
it.data().signature.name
|
||||
}.forEach {
|
||||
val diagnostics = it.getValue()
|
||||
if (diagnostics.size() <= 1) {
|
||||
filtered.addAll(diagnostics)
|
||||
}
|
||||
else {
|
||||
filtered.addAll(
|
||||
diagnostics.filter {
|
||||
me ->
|
||||
diagnostics.none {
|
||||
other ->
|
||||
me != other && (
|
||||
// in case of implementation copied from a super trait there will be both diagnostics on the same signature
|
||||
me.getFactory() == ACCIDENTAL_OVERRIDE && other.getFactory() == CONFLICTING_JVM_DECLARATIONS
|
||||
// there are paris of corresponding signatures that frequently clash simultaneously: package facade & part, trait and trait-impl
|
||||
|| other.data() higherThan me.data()
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered + other
|
||||
}
|
||||
|
||||
override fun all(): Collection<Diagnostic> {
|
||||
return jvmDiagnostics.all()
|
||||
.map { it.getPsiElement() }
|
||||
.toSet()
|
||||
.flatMap { forElement(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConflictingJvmDeclarationsData.higherThan(other: ConflictingJvmDeclarationsData): Boolean {
|
||||
return when (other.classOrigin.originKind) {
|
||||
PACKAGE_PART -> this.classOrigin.originKind == PACKAGE_FACADE
|
||||
TRAIT_IMPL -> this.classOrigin.originKind != TRAIT_IMPL
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2010-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 org.jetbrains.jet.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getNonStrictParentOfType
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
public fun JetClassOrObject.toLightClass(): KotlinLightClass? = LightClassUtil.getPsiClass(this) as KotlinLightClass?
|
||||
|
||||
public fun JetDeclaration.toLightElements(): List<PsiNamedElement> =
|
||||
when (this) {
|
||||
is JetClassOrObject -> Collections.singletonList(LightClassUtil.getPsiClass(this))
|
||||
is JetNamedFunction -> Collections.singletonList(LightClassUtil.getLightClassMethod(this))
|
||||
is JetProperty -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetPropertyAccessor -> Collections.singletonList(LightClassUtil.getLightClassAccessorMethod(this))
|
||||
is JetParameter -> ArrayList<PsiNamedElement>().let { elements ->
|
||||
toPsiParameter()?.let { psiParameter -> elements.add(psiParameter) }
|
||||
LightClassUtil.getLightClassPropertyMethods(this).toCollection(elements)
|
||||
|
||||
elements
|
||||
}
|
||||
is JetTypeParameter -> toPsiTypeParameters()
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
public fun PsiElement.toLightMethods(): List<PsiMethod> =
|
||||
when (this) {
|
||||
is JetNamedFunction -> LightClassUtil.getLightClassMethod(this).singletonOrEmptyList()
|
||||
is JetProperty -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetParameter -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(this).singletonOrEmptyList()
|
||||
is JetClass -> Collections.singletonList(LightClassUtil.getPsiClass(this).getConstructors()[0])
|
||||
is PsiMethod -> Collections.singletonList(this)
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
public fun PsiElement.getRepresentativeLightMethod(): PsiMethod? =
|
||||
when (this) {
|
||||
is JetNamedFunction -> LightClassUtil.getLightClassMethod(this)
|
||||
is JetProperty -> LightClassUtil.getLightClassPropertyMethods(this).getGetter()
|
||||
is JetParameter -> LightClassUtil.getLightClassPropertyMethods(this).getGetter()
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(this)
|
||||
is PsiMethod -> this
|
||||
else -> null
|
||||
}
|
||||
|
||||
public fun JetParameter.toPsiParameter(): PsiParameter? {
|
||||
val paramList = getNonStrictParentOfType<JetParameterList>()
|
||||
if (paramList == null) return null
|
||||
|
||||
val paramIndex = paramList.getParameters().indexOf(this)
|
||||
val owner = paramList.getParent()
|
||||
val lightParamIndex = if (owner != null && owner.isExtensionDeclaration()) paramIndex + 1 else paramIndex
|
||||
|
||||
val method: PsiMethod? = when (owner) {
|
||||
is JetNamedFunction -> LightClassUtil.getLightClassMethod(owner)
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(owner)
|
||||
is JetClass -> LightClassUtil.getPsiClass(owner)?.getConstructors()?.let { constructors ->
|
||||
if (constructors.isNotEmpty()) constructors[0] else null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
if (method == null) return null
|
||||
|
||||
return method.getParameterList().getParameters()[lightParamIndex]
|
||||
}
|
||||
|
||||
public fun JetTypeParameter.toPsiTypeParameters(): List<PsiTypeParameter> {
|
||||
val paramList = getNonStrictParentOfType<JetTypeParameterList>()
|
||||
if (paramList == null) return listOf()
|
||||
|
||||
val paramIndex = paramList.getParameters().indexOf(this)
|
||||
val jetDeclaration = paramList.getNonStrictParentOfType<JetDeclaration>() ?: return listOf()
|
||||
val lightOwners = jetDeclaration.toLightElements()
|
||||
|
||||
return lightOwners.map { lightOwner -> (lightOwner as PsiTypeParameterListOwner).getTypeParameters()[paramIndex] }
|
||||
}
|
||||
|
||||
// Returns original declaration if given PsiElement is a Kotlin light element, and element itself otherwise
|
||||
public val PsiElement.unwrapped: PsiElement?
|
||||
get() = if (this is KotlinLightElement<*, *>) origin else this
|
||||
|
||||
public val PsiElement.namedUnwrappedElement: PsiNamedElement?
|
||||
get() = unwrapped?.getNonStrictParentOfType<PsiNamedElement>()
|
||||
Reference in New Issue
Block a user