Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="IDEA 10.x" jdkType="IDEA JDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
@@ -21,6 +22,7 @@
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
<orderEntry type="module" module-name="compiler-tests" />
|
||||
<orderEntry type="module" module-name="jet.as.java.psi" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#parse("File Header.java")
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse">
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<font face="verdana" size="-1">
|
||||
This is a built-in template used by <b>IDEA</b> each time you create a
|
||||
Kotlin file
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,6 +14,10 @@
|
||||
</project-components>
|
||||
|
||||
<actions>
|
||||
<action id="Kotlin.NewFile" class="org.jetbrains.jet.plugin.actions.NewKotlinFileAction">
|
||||
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFromTemplate"/>
|
||||
</action>
|
||||
|
||||
<action id="ShowJetExpressionType" class="org.jetbrains.jet.plugin.actions.ShowExpressionTypeAction"
|
||||
text="Show Expression Type">
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="control shift Q"/>
|
||||
@@ -32,6 +36,9 @@
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
<internalFileTemplate name="Kotlin File"/>
|
||||
|
||||
<fileTypeFactory implementation="org.jetbrains.jet.plugin.JetFileFactory"/>
|
||||
<lang.syntaxHighlighterFactory key="jet" implementationClass="org.jetbrains.jet.plugin.JetSyntaxHighlighterFactory"/>
|
||||
<lang.braceMatcher language="jet" implementationClass="org.jetbrains.jet.plugin.JetPairMatcher"/>
|
||||
@@ -59,8 +66,8 @@
|
||||
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||
|
||||
|
||||
<java.elementFinder implementation="org.jetbrains.jet.plugin.java.JavaElementFinder"/>
|
||||
<psi.treeChangePreprocessor implementation="org.jetbrains.jet.plugin.java.JetCodeBlockModificationListener"/>
|
||||
<java.elementFinder implementation="org.jetbrains.jet.asJava.JavaElementFinder"/>
|
||||
<psi.treeChangePreprocessor implementation="org.jetbrains.jet.asJava.JetCodeBlockModificationListener"/>
|
||||
|
||||
<toolWindow id="CodeWindow"
|
||||
factoryClass="org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow$Factory"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.plugin;
|
||||
|
||||
import com.intellij.ide.IconProvider;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -16,9 +17,13 @@ import javax.swing.*;
|
||||
*/
|
||||
public class JetIconProvider extends IconProvider {
|
||||
public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON;
|
||||
public static final Icon KOTLIN_ICON = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png");
|
||||
|
||||
@Override
|
||||
public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
|
||||
if (psiElement instanceof JetFile) {
|
||||
return KOTLIN_ICON;
|
||||
}
|
||||
if (psiElement instanceof JetNamespaceHeader) {
|
||||
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.jet.plugin.actions;
|
||||
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.actions.CreateFromTemplateAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.jet.plugin.JetIconProvider;
|
||||
|
||||
/**
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class NewKotlinFileAction extends CreateFromTemplateAction {
|
||||
|
||||
public NewKotlinFileAction() {
|
||||
super(FileTemplateManager.getInstance().getInternalTemplate("Kotlin File"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
e.getPresentation().setIcon(JetIconProvider.KOTLIN_ICON);
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
if (element instanceof JetNamedFunction) {
|
||||
JetNamedFunction jetFunction = (JetNamedFunction) element;
|
||||
|
||||
final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, jetFunction);
|
||||
final NamedFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, jetFunction);
|
||||
if (functionDescriptor == null) return null;
|
||||
final Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||
Icon icon = isMember(functionDescriptor) ? (overriddenFunctions.isEmpty() ? PlatformIcons.METHOD_ICON : OVERRIDING_FUNCTION) : PlatformIcons.FUNCTION_ICON;
|
||||
@@ -182,7 +182,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isMember(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
private boolean isMember(@NotNull NamedFunctionDescriptor functionDescriptor) {
|
||||
return functionDescriptor.getContainingDeclaration().getOriginal() instanceof ClassifierDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
||||
}
|
||||
for (DescriptorClassMember selectedElement : selectedElements) {
|
||||
final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
JetElement target = overrideFunction(project, (FunctionDescriptor) descriptor);
|
||||
if (descriptor instanceof NamedFunctionDescriptor) {
|
||||
JetElement target = overrideFunction(project, (NamedFunctionDescriptor) descriptor);
|
||||
body.addBefore(target, body.getRBrace());
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
@@ -84,7 +84,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
||||
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
||||
}
|
||||
|
||||
private static JetElement overrideFunction(Project project, FunctionDescriptor descriptor) {
|
||||
private static JetElement overrideFunction(Project project, NamedFunctionDescriptor descriptor) {
|
||||
StringBuilder bodyBuilder = new StringBuilder("override fun ");
|
||||
bodyBuilder.append(descriptor.getName());
|
||||
bodyBuilder.append("(");
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.java;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
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.ClsMethodImpl;
|
||||
import com.intellij.psi.impl.java.stubs.*;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
public static final Key<PsiElement> ORIGIN_ELEMENT = Key.create("ORIGIN_ELEMENT");
|
||||
private final StubPsiFactory delegate = new ClsStubPsiFactory();
|
||||
|
||||
@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) {
|
||||
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||
if (origin == null) return delegate.createMethod(stub);
|
||||
|
||||
return new ClsMethodImpl(stub) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return origin;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.java;
|
||||
|
||||
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.file.PsiPackageImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JavaElementFinder extends PsiElementFinder {
|
||||
private final Project project;
|
||||
private final PsiManager psiManager;
|
||||
|
||||
private WeakHashMap<GlobalSearchScope, List<JetFile>> jetFiles = new WeakHashMap<GlobalSearchScope, List<JetFile>>();
|
||||
|
||||
public JavaElementFinder(Project project) {
|
||||
this.project = project;
|
||||
psiManager = PsiManager.getInstance(project);
|
||||
|
||||
// Monitoring for files instead of collecting them each time
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() {
|
||||
@Override
|
||||
public void fileCreated(VirtualFileEvent event) {
|
||||
invalidateJetFilesCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileDeleted(VirtualFileEvent event) {
|
||||
invalidateJetFilesCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileMoved(VirtualFileMoveEvent event) {
|
||||
invalidateJetFilesCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileCopied(VirtualFileCopyEvent event) {
|
||||
invalidateJetFilesCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||
final PsiClass[] allClasses = findClasses(qualifiedName, scope);
|
||||
return allClasses.length > 0 ? allClasses[0] : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||
// Backend searches for java.lang.String. Will fail with SOE if continue
|
||||
if (qualifiedName.startsWith("java.")) return PsiClass.EMPTY_ARRAY;
|
||||
|
||||
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||
final List<JetFile> filesInScope = collectProjectJetFiles(project, scope);
|
||||
for (JetFile file : filesInScope) {
|
||||
final String packageName = JetPsiUtil.getFQName(file);
|
||||
if (packageName != null && qualifiedName.startsWith(packageName)) {
|
||||
if (qualifiedName.equals(fqn(packageName, JvmAbi.PACKAGE_CLASS))) {
|
||||
answer.add(new JetLightClass(psiManager, file, qualifiedName));
|
||||
}
|
||||
else {
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
scanClasses(answer, declaration, qualifiedName, packageName, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
private void scanClasses(List<PsiClass> answer, JetDeclaration declaration, String qualifiedName, String containerFqn, JetFile file) {
|
||||
if (declaration instanceof JetClassOrObject) {
|
||||
String localName = getLocalName(declaration);
|
||||
if (localName != null) {
|
||||
String fqn = fqn(containerFqn, localName);
|
||||
if (qualifiedName.equals(fqn)) {
|
||||
answer.add(new JetLightClass(psiManager, file, qualifiedName));
|
||||
}
|
||||
else {
|
||||
for (JetDeclaration child : ((JetClassOrObject) declaration).getDeclarations()) {
|
||||
scanClasses(answer, child, qualifiedName, fqn, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetClassObject) {
|
||||
scanClasses(answer, ((JetClassObject) declaration).getObjectDeclaration(), qualifiedName, containerFqn, file);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLocalName(JetDeclaration declaration) {
|
||||
String given = declaration.getName();
|
||||
if (given != null) return given;
|
||||
|
||||
if (declaration instanceof JetObjectDeclaration) {
|
||||
return JetTypeMapper.getLocalNameForObject((JetObjectDeclaration) declaration);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
Set<String> answer = new HashSet<String>();
|
||||
|
||||
String packageFQN = psiPackage.getQualifiedName();
|
||||
for (JetFile psiFile : collectProjectJetFiles(project, GlobalSearchScope.allScope(project))) {
|
||||
if (packageFQN.equals(JetPsiUtil.getFQName(psiFile))) {
|
||||
answer.add(JvmAbi.PACKAGE_CLASS);
|
||||
for (JetDeclaration declaration : psiFile.getDeclarations()) {
|
||||
if (declaration instanceof JetClassOrObject) {
|
||||
answer.add(getLocalName(declaration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
private static String fqn(String packageName, String className) {
|
||||
if (StringUtil.isEmpty(packageName)) return className;
|
||||
return packageName + "." + className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiPackage findPackage(@NotNull String qualifiedName) {
|
||||
final List<JetFile> psiFiles = collectProjectJetFiles(project, GlobalSearchScope.allScope(project));
|
||||
|
||||
for (JetFile psiFile : psiFiles) {
|
||||
if (qualifiedName.equals(JetPsiUtil.getFQName(psiFile))) {
|
||||
return new PsiPackageImpl(psiFile.getManager(), qualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
List<PsiClass> answer = new SmartList<PsiClass>();
|
||||
final List<JetFile> filesInScope = collectProjectJetFiles(project, scope);
|
||||
String packageFQN = psiPackage.getQualifiedName();
|
||||
for (JetFile file : filesInScope) {
|
||||
if (packageFQN.equals(JetPsiUtil.getFQName(file))) {
|
||||
answer.add(new JetLightClass(psiManager, file, fqn(packageFQN, JvmAbi.PACKAGE_CLASS)));
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetClassOrObject) {
|
||||
answer.add(new JetLightClass(psiManager, file, fqn(packageFQN, getLocalName(declaration))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
private synchronized void invalidateJetFilesCache() {
|
||||
jetFiles.clear();
|
||||
}
|
||||
|
||||
private synchronized List<JetFile> collectProjectJetFiles(final Project project, @NotNull final GlobalSearchScope scope) {
|
||||
List<JetFile> cachedFiles = jetFiles.get(scope);
|
||||
|
||||
if (cachedFiles == null) {
|
||||
final List<JetFile> answer = new ArrayList<JetFile>();
|
||||
|
||||
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
|
||||
|
||||
VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||
|
||||
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
|
||||
@Override
|
||||
protected void acceptFile(VirtualFile file, String fileRoot, String filePath) {
|
||||
final FileType fileType = fileTypeManager.getFileTypeByFile(file);
|
||||
if (fileType != JetFileType.INSTANCE) return;
|
||||
|
||||
if (scope.accept(file)) {
|
||||
final PsiFile psiFile = psiManager.findFile(file);
|
||||
if (psiFile instanceof JetFile) {
|
||||
answer.add((JetFile) psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cachedFiles = answer;
|
||||
jetFiles.put(scope, answer);
|
||||
}
|
||||
|
||||
return cachedFiles;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.java;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import org.jetbrains.jet.lang.psi.JetBlockExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
public class JetCodeBlockModificationListener implements PsiTreeChangePreprocessor {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.plugin.java.JetCodeBlockModificationListener");
|
||||
|
||||
private final PsiModificationTrackerImpl myModificationTracker;
|
||||
|
||||
public JetCodeBlockModificationListener(final PsiModificationTracker modificationTracker) {
|
||||
myModificationTracker = (PsiModificationTrackerImpl) modificationTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void treeChanged(final PsiTreeChangeEventImpl event) {
|
||||
switch (event.getCode()) {
|
||||
case BEFORE_CHILDREN_CHANGE:
|
||||
case BEFORE_PROPERTY_CHANGE:
|
||||
case BEFORE_CHILD_MOVEMENT:
|
||||
case BEFORE_CHILD_REPLACEMENT:
|
||||
case BEFORE_CHILD_ADDITION:
|
||||
case BEFORE_CHILD_REMOVAL:
|
||||
break;
|
||||
|
||||
case CHILD_ADDED:
|
||||
case CHILD_REMOVED:
|
||||
case CHILD_REPLACED:
|
||||
processChange(event.getParent(), event.getOldChild(), event.getChild());
|
||||
break;
|
||||
|
||||
case CHILDREN_CHANGED:
|
||||
// general childrenChanged() event after each change
|
||||
if (!event.isGenericChildrenChange()) {
|
||||
processChange(event.getParent(), event.getParent(), null);
|
||||
}
|
||||
break;
|
||||
|
||||
case CHILD_MOVED:
|
||||
case PROPERTY_CHANGED:
|
||||
myModificationTracker.incCounter();
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG.error("Unknown code:" + event.getCode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processChange(final PsiElement parent, final PsiElement child1, final PsiElement child2) {
|
||||
try {
|
||||
if (!isInsideCodeBlock(parent)) {
|
||||
if (parent != null && parent.getContainingFile() instanceof JetFile) {
|
||||
myModificationTracker.incCounter();
|
||||
}
|
||||
else {
|
||||
myModificationTracker.incOutOfCodeBlockModificationCounter();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (containsClassesInside(child1) || child2 != child1 && containsClassesInside(child2)) {
|
||||
myModificationTracker.incCounter();
|
||||
}
|
||||
} catch (PsiInvalidElementAccessException e) {
|
||||
myModificationTracker.incCounter(); // Shall not happen actually, just a pre-release paranoia
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean containsClassesInside(final PsiElement element) {
|
||||
if (element == null) return false;
|
||||
if (element instanceof PsiClass) return true;
|
||||
|
||||
PsiElement child = element.getFirstChild();
|
||||
while (child != null) {
|
||||
if (containsClassesInside(child)) return true;
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isInsideCodeBlock(PsiElement element) {
|
||||
if (element instanceof PsiFileSystemItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (element == null || element.getParent() == null) return true;
|
||||
|
||||
PsiElement parent = element;
|
||||
while (true) {
|
||||
if (parent instanceof PsiFile || parent instanceof PsiDirectory || parent == null) {
|
||||
return false;
|
||||
}
|
||||
if (parent instanceof JetClass) return false; // anonymous or local class
|
||||
if (parent instanceof JetBlockExpression) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.java;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassStub;
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
|
||||
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
|
||||
import com.intellij.psi.impl.light.AbstractLightClass;
|
||||
import com.intellij.psi.stubs.PsiClassHolderFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
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.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.resolve.java.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMarker {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.plugin.java.JetLightClass");
|
||||
private final static Key<CachedValue<PsiJavaFileStub>> JAVA_API_STUB = Key.create("JAVA_API_STUB");
|
||||
|
||||
private final JetFile file;
|
||||
private final String qualifiedName;
|
||||
private PsiClass delegate;
|
||||
|
||||
public JetLightClass(PsiManager manager, JetFile file, String qualifiedName) {
|
||||
super(manager, JetLanguage.INSTANCE);
|
||||
this.file = file;
|
||||
this.qualifiedName = qualifiedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
int idx = qualifiedName.lastIndexOf('.');
|
||||
return idx > 0 ? qualifiedName.substring(idx + 1) : qualifiedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new JetLightClass(getManager(), file, qualifiedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile getContainingFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getDelegate() {
|
||||
if (delegate == null) {
|
||||
delegate = findClass(qualifiedName, getStub());
|
||||
if (delegate == null) {
|
||||
delegate = findClass(qualifiedName, getStub());
|
||||
}
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private static PsiClass findClass(String fqn, StubElement<?> stub) {
|
||||
if (stub instanceof PsiClassStub && Comparing.equal(fqn, ((PsiClassStub) stub).getQualifiedName())) {
|
||||
return (PsiClass) stub.getPsi();
|
||||
}
|
||||
|
||||
for (StubElement child : stub.getChildrenStubs()) {
|
||||
PsiClass answer = findClass(fqn, child);
|
||||
if (answer != null) return answer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQualifiedName() {
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
private PsiJavaFileStub getStub() {
|
||||
CachedValue<PsiJavaFileStub> answer = file.getUserData(JAVA_API_STUB);
|
||||
if (answer == null) {
|
||||
answer = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<PsiJavaFileStub>() {
|
||||
@Override
|
||||
public Result<PsiJavaFileStub> compute() {
|
||||
return Result.create(calcStub(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
file.putUserData(JAVA_API_STUB, answer);
|
||||
}
|
||||
|
||||
return answer.getValue();
|
||||
}
|
||||
|
||||
private PsiJavaFileStub calcStub() {
|
||||
final PsiJavaFileStubImpl answer = new PsiJavaFileStubImpl(JetPsiUtil.getFQName(file), true);
|
||||
final Project project = getProject();
|
||||
|
||||
final Stack<StubElement> stubStack = new Stack<StubElement>();
|
||||
|
||||
final ClassBuilderFactory builderFactory = new ClassBuilderFactory() {
|
||||
@Override
|
||||
public ClassBuilder newClassBuilder() {
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
final GenerationState state = new GenerationState(project, builderFactory) {
|
||||
@Override
|
||||
protected void generateNamespace(JetFile namespace) {
|
||||
PsiManager manager = PsiManager.getInstance(project);
|
||||
stubStack.push(answer);
|
||||
|
||||
answer.setPsiFactory(new ClsWrapperStubPsiFactory());
|
||||
final ClsFileImpl fakeFile = new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, file.getVirtualFile())) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassHolderFileStub getStub() {
|
||||
return answer;
|
||||
}
|
||||
};
|
||||
|
||||
fakeFile.setPhysical(false);
|
||||
answer.setPsi(fakeFile);
|
||||
|
||||
try {
|
||||
super.generateNamespace(namespace);
|
||||
}
|
||||
finally {
|
||||
final StubElement pop = stubStack.pop();
|
||||
if (pop != answer) {
|
||||
LOG.error("Unbalanced stack operations: " + pop);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
List<JetFile> files = Collections.singletonList(file);
|
||||
final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files);
|
||||
state.compileCorrectFiles(context, files);
|
||||
state.getFactory().files();
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
return another instanceof PsiClass && Comparing.equal(((PsiClass) another).getQualifiedName(), getQualifiedName());
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.plugin.java;
|
||||
|
||||
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.Nullable;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StubClassBuilder extends ClassBuilder {
|
||||
private static final InnerClassSourceStrategy<Object> EMPTY_STRATEGY = new InnerClassSourceStrategy<Object>() {
|
||||
@Override
|
||||
public Object findInnerClass(String s, Object o) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassReader readerForInnerClass(Object o) {
|
||||
throw new UnsupportedOperationException("Shall not be called!");
|
||||
}
|
||||
};
|
||||
private final StubElement parent;
|
||||
private StubBuildingVisitor v;
|
||||
private final Stack<StubElement> parentStack;
|
||||
private boolean isNamespace = false;
|
||||
|
||||
public StubClassBuilder(Stack<StubElement> parentStack) {
|
||||
this.parentStack = parentStack;
|
||||
this.parent = parentStack.peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassVisitor getVisitor() {
|
||||
assert v != null : "Called before class is defined";
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
|
||||
assert v == null : "defineClass() called twice?";
|
||||
v = new StubBuildingVisitor<Object>(null, EMPTY_STRATEGY, parent, access);
|
||||
|
||||
super.defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
if (name.equals(JvmAbi.PACKAGE_CLASS) || name.endsWith("/" + JvmAbi.PACKAGE_CLASS)) {
|
||||
isNamespace = true;
|
||||
}
|
||||
else {
|
||||
parentStack.push(v.getResult());
|
||||
}
|
||||
|
||||
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor newMethod(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) {
|
||||
final MethodVisitor answer = super.newMethod(origin, access, name, desc, signature, exceptions);
|
||||
markLastChild(origin);
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor newField(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable Object value) {
|
||||
final FieldVisitor answer = super.newField(origin, access, name, desc, signature, value);
|
||||
markLastChild(origin);
|
||||
return answer;
|
||||
}
|
||||
|
||||
private void markLastChild(PsiElement origin) {
|
||||
final List children = v.getResult().getChildrenStubs();
|
||||
StubBase last = (StubBase) children.get(children.size() - 1);
|
||||
last.putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
if (!isNamespace) {
|
||||
final StubElement pop = parentStack.pop();
|
||||
assert pop == v.getResult();
|
||||
}
|
||||
super.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateCode() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||
@@ -83,6 +83,8 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
}
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (declarationDescriptors != null) return null;
|
||||
|
||||
// TODO: Need a better resolution for intrinsic function (KT-975)
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -91,15 +93,19 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY;
|
||||
ResolveResult[] results = new ResolveResult[declarationDescriptors.size()];
|
||||
int i = 0;
|
||||
|
||||
ArrayList<ResolveResult> results = new ArrayList<ResolveResult>(declarationDescriptors.size());
|
||||
|
||||
for (DeclarationDescriptor descriptor : declarationDescriptors) {
|
||||
PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
if (element != null) {
|
||||
results[i] = new PsiElementResolveResult(element, true);
|
||||
i++;
|
||||
if (element == null) {
|
||||
// TODO: Need a better resolution for intrinsic function (KT-975)
|
||||
element = file;
|
||||
}
|
||||
|
||||
results.add(new PsiElementResolveResult(element, true));
|
||||
}
|
||||
return results;
|
||||
|
||||
return results.toArray(new ResolveResult[results.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,16 @@ import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PsiIconUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -19,8 +27,17 @@ import java.util.List;
|
||||
public class JetStructureViewElement implements StructureViewTreeElement {
|
||||
private final NavigatablePsiElement myElement;
|
||||
|
||||
public JetStructureViewElement(NavigatablePsiElement element) {
|
||||
// For file context will be updated after each construction
|
||||
// For other tree sub-elements it's immutable.
|
||||
private BindingContext context;
|
||||
|
||||
public JetStructureViewElement(NavigatablePsiElement element, BindingContext context) {
|
||||
myElement = element;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public JetStructureViewElement(JetFile fileElement) {
|
||||
myElement = fileElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,13 +65,29 @@ public class JetStructureViewElement implements StructureViewTreeElement {
|
||||
return new ItemPresentation() {
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
String name = myElement.getName();
|
||||
if (StringUtil.isEmpty(name)) {
|
||||
String text = "";
|
||||
|
||||
// Try to find text in correspondent descriptor
|
||||
// if (myElement instanceof JetDeclaration) {
|
||||
// JetDeclaration declaration = (JetDeclaration) myElement;
|
||||
// final DeclarationDescriptor descriptor =
|
||||
// context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
|
||||
//
|
||||
// if (descriptor != null) {
|
||||
// text = getDescriptorTreeText(descriptor);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (StringUtil.isEmpty(text)) {
|
||||
text = myElement.getName();
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(text)) {
|
||||
if (myElement instanceof JetClassInitializer) {
|
||||
return "<class initializer>";
|
||||
}
|
||||
}
|
||||
return name;
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,20 +97,26 @@ public class JetStructureViewElement implements StructureViewTreeElement {
|
||||
|
||||
@Override
|
||||
public Icon getIcon(boolean open) {
|
||||
return myElement.isValid()
|
||||
? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED)
|
||||
: null;
|
||||
if (myElement.isValid()) {
|
||||
return PsiIconUtil.getProvidersIcon(
|
||||
myElement,
|
||||
open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TreeElement[] getChildren() {
|
||||
if (myElement instanceof JetFile) {
|
||||
return new TreeElement[] { new JetStructureViewElement(myElement) };
|
||||
}
|
||||
else if (myElement instanceof JetFile) {
|
||||
return wrapDeclarations(((JetFile) myElement).getDeclarations());
|
||||
final JetFile jetFile = (JetFile) myElement;
|
||||
|
||||
// TODO: Understand why it significantly reduce responsibility of IDEA during typing
|
||||
// context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
|
||||
|
||||
return wrapDeclarations(jetFile.getDeclarations());
|
||||
}
|
||||
else if (myElement instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) myElement;
|
||||
@@ -89,19 +128,68 @@ public class JetStructureViewElement implements StructureViewTreeElement {
|
||||
}
|
||||
declarations.addAll(jetClass.getDeclarations());
|
||||
return wrapDeclarations(declarations);
|
||||
|
||||
}
|
||||
else if (myElement instanceof JetClassOrObject) {
|
||||
return wrapDeclarations(((JetClassOrObject) myElement).getDeclarations());
|
||||
}
|
||||
return new TreeElement[0];
|
||||
}
|
||||
|
||||
private static TreeElement[] wrapDeclarations(List<JetDeclaration> declarations) {
|
||||
|
||||
private TreeElement[] wrapDeclarations(List<JetDeclaration> declarations) {
|
||||
TreeElement[] result = new TreeElement[declarations.size()];
|
||||
for (int i = 0; i < declarations.size(); i++) {
|
||||
result[i] = new JetStructureViewElement(declarations.get(i));
|
||||
result[i] = new JetStructureViewElement(declarations.get(i), context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getDescriptorTreeText(@NotNull DeclarationDescriptor descriptor) {
|
||||
StringBuilder textBuilder;
|
||||
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
textBuilder = new StringBuilder();
|
||||
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
ReceiverDescriptor receiver = functionDescriptor.getReceiverParameter();
|
||||
if (receiver.exists()) {
|
||||
textBuilder.append(DescriptorRenderer.TEXT.renderType(receiver.getType())).append(".");
|
||||
}
|
||||
|
||||
textBuilder.append(functionDescriptor.getName());
|
||||
|
||||
String parametersString = StringUtil.join(
|
||||
functionDescriptor.getValueParameters(),
|
||||
new Function<ValueParameterDescriptor, String>() {
|
||||
@Override
|
||||
public String fun(ValueParameterDescriptor valueParameterDescriptor) {
|
||||
return valueParameterDescriptor.getName() + ":" +
|
||||
DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType());
|
||||
}
|
||||
},
|
||||
",");
|
||||
|
||||
textBuilder.append("(").append(parametersString).append(")");
|
||||
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
textBuilder.append(":").append(DescriptorRenderer.TEXT.renderType(returnType));
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor) {
|
||||
JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
||||
|
||||
textBuilder = new StringBuilder(descriptor.getName());
|
||||
textBuilder.append(":").append(DescriptorRenderer.TEXT.renderType(outType));
|
||||
}
|
||||
else if (descriptor instanceof ClassDescriptor) {
|
||||
textBuilder = new StringBuilder(descriptor.getName());
|
||||
textBuilder
|
||||
.append(" (")
|
||||
.append(DescriptorUtils.getFQName(descriptor.getContainingDeclaration()))
|
||||
.append(")");
|
||||
}
|
||||
else {
|
||||
return DescriptorRenderer.TEXT.render(descriptor);
|
||||
}
|
||||
|
||||
return textBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
|
||||
import com.intellij.lang.PsiStructureViewFactory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -13,12 +14,18 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class JetStructureViewFactory implements PsiStructureViewFactory {
|
||||
@Override
|
||||
public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
|
||||
return new TreeBasedStructureViewBuilder() {
|
||||
@NotNull
|
||||
@Override
|
||||
public StructureViewModel createStructureViewModel() {
|
||||
return new JetStructureViewModel(psiFile);
|
||||
}
|
||||
};
|
||||
if (psiFile instanceof JetFile) {
|
||||
final JetFile file = (JetFile) psiFile;
|
||||
|
||||
return new TreeBasedStructureViewBuilder() {
|
||||
@NotNull
|
||||
@Override
|
||||
public StructureViewModel createStructureViewModel() {
|
||||
return new JetStructureViewModel(file);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package org.jetbrains.jet.plugin.structureView;
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewModelBase;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class JetStructureViewModel extends StructureViewModelBase {
|
||||
public JetStructureViewModel(@NotNull PsiFile psiFile) {
|
||||
super(psiFile, new JetStructureViewElement(psiFile));
|
||||
public JetStructureViewModel(@NotNull JetFile jetFile) {
|
||||
super(jetFile, new JetStructureViewElement(jetFile));
|
||||
withSuitableClasses(JetDeclaration.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package ctrl_click
|
||||
|
||||
fun IntArray(vararg content : Int) : IntArray = content
|
||||
fun <T> array(vararg t : T) : Array<T> = t
|
||||
|
||||
fun main(args : ArrayList<String>) {
|
||||
var a = <caret>IntArray(array(1, 2, 3))
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.jetbrains.jet.resolve;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class ResolveBaseTest extends LightCodeInsightTestCase {
|
||||
|
||||
private final String myPath;
|
||||
private final String myName;
|
||||
|
||||
protected ResolveBaseTest(@NotNull String path, @NotNull String name) {
|
||||
myPath = path;
|
||||
myName = name;
|
||||
|
||||
// Set name explicitly because otherwise there will be "TestCase.fName cannot be null"
|
||||
setName("testResolve");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return PluginTestCaseBase.jdkFromIdeaHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return new File(PluginTestCaseBase.getTestDataPathBase(), myPath).getPath() +
|
||||
File.separator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "test" + myName;
|
||||
}
|
||||
|
||||
public void testResolve() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// TODO: Currently this test is only for KT-763 bug - it should be extended to framework for testing references
|
||||
protected void doTest() throws Exception {
|
||||
final String testName = getTestName(false);
|
||||
configureByFile(testName + ".kt");
|
||||
|
||||
final PsiReference psiReference =
|
||||
getFile().findReferenceAt(getEditor().getCaretModel().getOffset());
|
||||
|
||||
assertTrue(psiReference instanceof PsiPolyVariantReference);
|
||||
|
||||
final PsiPolyVariantReference variantReference = (PsiPolyVariantReference) psiReference;
|
||||
|
||||
final ResolveResult[] results = variantReference.multiResolve(true);
|
||||
for (ResolveResult result : results) {
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TestSuite suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
JetTestCaseBuilder.appendTestsInDirectory(
|
||||
PluginTestCaseBase.getTestDataPathBase(), "/resolve/", false,
|
||||
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
|
||||
return new ResolveBaseTest(dataPath, name);
|
||||
}
|
||||
}, suite);
|
||||
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user