delete the UI for editing Kotlin signatures in Java files
This commit is contained in:
@@ -27,9 +27,6 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.NonConfiguredKotlinProjectComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.ktSignature.KotlinSignatureInJavaMarkerUpdater</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager</implementation-class>
|
||||
</component>
|
||||
@@ -84,11 +81,6 @@
|
||||
<add-to-group group-id="CodeMenu" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<group id="EditorGutterKotlinPopupMenu">
|
||||
<action id="ShowKotlinSignatures" class="org.jetbrains.kotlin.idea.ktSignature.ShowKotlinSignaturesAction"/>
|
||||
<add-to-group group-id="EditorGutterPopupMenu" anchor="last"/>
|
||||
</group>
|
||||
|
||||
<group id="KotlinToolsGroup" popup="true" text="Kotlin" icon="/org/jetbrains/kotlin/idea/icons/kotlin13.png"
|
||||
class="org.jetbrains.kotlin.idea.actions.KotlinActionGroup">
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
@@ -407,8 +399,6 @@
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinRunConfigurationProducer"/>
|
||||
<codeInsight.lineMarkerProvider language="jet" implementationClass="org.jetbrains.kotlin.idea.highlighter.markers.KotlinLineMarkerProvider"/>
|
||||
<codeInsight.lineMarkerProvider language="jet" implementationClass="org.jetbrains.kotlin.idea.highlighter.KotlinRecursiveCallLineMarkerProvider"/>
|
||||
<codeInsight.lineMarkerProvider language="JAVA"
|
||||
implementationClass="org.jetbrains.kotlin.idea.ktSignature.KotlinSignatureInJavaMarkerProvider"/>
|
||||
<iconProvider implementation="org.jetbrains.kotlin.idea.JetIconProvider"/>
|
||||
<itemPresentationProvider implementationClass="org.jetbrains.kotlin.idea.presentation.JetFunctionPresenter"
|
||||
forClass="org.jetbrains.kotlin.psi.JetFunction"/>
|
||||
@@ -576,11 +566,6 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.ktSignature.KotlinSignatureAnnotationIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.FoldIfToAssignmentIntention</className>
|
||||
<category>Kotlin</category>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SIGNATURE;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.OLD_KOTLIN_SIGNATURE;
|
||||
|
||||
public class DeleteSignatureAction extends AnAction {
|
||||
private final PsiModifierListOwner annotationOwner;
|
||||
|
||||
public DeleteSignatureAction(@NotNull PsiModifierListOwner elementInEditor) {
|
||||
super("Delete");
|
||||
this.annotationOwner = KotlinSignatureUtil.getAnalyzableAnnotationOwner(elementInEditor);
|
||||
getTemplatePresentation().setVisible(annotationOwner != null && KotlinSignatureUtil.isAnnotationEditable(elementInEditor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getProject();
|
||||
assert project != null;
|
||||
|
||||
final PsiAnnotation annotation = KotlinSignatureUtil.findKotlinSignatureAnnotation(annotationOwner);
|
||||
assert annotation != null;
|
||||
|
||||
if (annotation.getContainingFile() != annotationOwner.getContainingFile()) {
|
||||
// external annotation
|
||||
new WriteCommandAction(project) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
ExternalAnnotationsManager.getInstance(project).deannotate(annotationOwner, KOTLIN_SIGNATURE.asString());
|
||||
ExternalAnnotationsManager.getInstance(project).deannotate(annotationOwner, OLD_KOTLIN_SIGNATURE.asString());
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
else {
|
||||
new WriteCommandAction(project) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
annotation.delete();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|
||||
KotlinSignatureUtil.refreshMarkers(project);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class EditSignatureAction extends AnAction {
|
||||
private final PsiModifierListOwner elementInEditor;
|
||||
|
||||
public EditSignatureAction(@NotNull PsiModifierListOwner elementInEditor) {
|
||||
super(KotlinSignatureUtil.isAnnotationEditable(elementInEditor) ? "Edit" : "View");
|
||||
this.elementInEditor = elementInEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
actionPerformed(e.getDataContext(), null);
|
||||
}
|
||||
|
||||
public void actionPerformed(@NotNull DataContext dataContext, @Nullable Point point) {
|
||||
Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
|
||||
assert editor != null;
|
||||
invokeEditSignature(elementInEditor, editor, point);
|
||||
}
|
||||
|
||||
static void invokeEditSignature(@NotNull PsiElement elementInEditor, @NotNull Editor editor, @Nullable Point point) {
|
||||
PsiAnnotation annotation = KotlinSignatureUtil.findKotlinSignatureAnnotation(elementInEditor);
|
||||
assert annotation != null;
|
||||
if (annotation.getContainingFile() == elementInEditor.getContainingFile()) {
|
||||
// not external, go to
|
||||
for (PsiNameValuePair pair : annotation.getParameterList().getAttributes()) {
|
||||
if (pair.getName() == null || "value".equals(pair.getName())) {
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (value != null) {
|
||||
VirtualFile virtualFile = value.getContainingFile().getVirtualFile();
|
||||
assert virtualFile != null;
|
||||
|
||||
PsiElement firstChild = value.getFirstChild();
|
||||
if (firstChild != null && firstChild.getNode().getElementType() == JavaTokenType.STRING_LITERAL) {
|
||||
new OpenFileDescriptor(value.getProject(), virtualFile, value.getTextOffset() + 1).navigate(true);
|
||||
}
|
||||
else {
|
||||
NavigationUtil.activateFileWithPsiElement(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiModifierListOwner annotationOwner = KotlinSignatureUtil.getAnalyzableAnnotationOwner(elementInEditor);
|
||||
boolean editable = KotlinSignatureUtil.isAnnotationEditable(elementInEditor);
|
||||
//noinspection ConstantConditions
|
||||
EditSignatureBalloon balloon = new EditSignatureBalloon(annotationOwner, KotlinSignatureUtil.getKotlinSignature(annotation),
|
||||
editable, annotation.getQualifiedName());
|
||||
balloon.show(point, editor, elementInEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.JBPopupAdapter;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.JetFileType;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
class EditSignatureBalloon implements Disposable {
|
||||
private final Editor editor;
|
||||
private final PsiModifierListOwner annotatedElement;
|
||||
private final Project project;
|
||||
private final String previousSignature;
|
||||
private final MyPanel panel;
|
||||
private final Balloon balloon;
|
||||
private final boolean editable;
|
||||
private final String kotlinSignatureAnnotationFqName;
|
||||
|
||||
public EditSignatureBalloon(
|
||||
@NotNull PsiModifierListOwner annotatedElement,
|
||||
@NotNull String previousSignature,
|
||||
boolean editable,
|
||||
@NotNull String kotlinSignatureAnnotationFqName
|
||||
) {
|
||||
this.annotatedElement = annotatedElement;
|
||||
this.previousSignature = previousSignature;
|
||||
this.editable = editable;
|
||||
this.kotlinSignatureAnnotationFqName = kotlinSignatureAnnotationFqName;
|
||||
|
||||
project = annotatedElement.getProject();
|
||||
editor = createEditor();
|
||||
panel = new MyPanel();
|
||||
balloon = createBalloon();
|
||||
}
|
||||
|
||||
private Balloon createBalloon() {
|
||||
Balloon balloon = JBPopupFactory.getInstance().createDialogBalloonBuilder(panel, "Kotlin signature")
|
||||
.setHideOnClickOutside(true)
|
||||
.setHideOnKeyOutside(true)
|
||||
.setBlockClicksThroughBalloon(true).createBalloon();
|
||||
|
||||
balloon.addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
Disposer.dispose(EditSignatureBalloon.this);
|
||||
}
|
||||
});
|
||||
return balloon;
|
||||
}
|
||||
|
||||
private Editor createEditor() {
|
||||
EditorFactory editorFactory = EditorFactory.getInstance();
|
||||
assert editorFactory != null;
|
||||
LightVirtualFile virtualFile = new LightVirtualFile("signature.kt", JetFileType.INSTANCE, previousSignature);
|
||||
virtualFile.setWritable(editable);
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
|
||||
assert document != null;
|
||||
|
||||
document.addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent event) {
|
||||
PsiDocumentManager psiDocManager = PsiDocumentManager.getInstance(project);
|
||||
|
||||
final PsiFile psiFile = psiDocManager.getPsiFile(document);
|
||||
assert psiFile instanceof JetFile;
|
||||
|
||||
psiDocManager.performForCommittedDocument(document, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
panel.setSaveButtonEnabled(hasErrors((JetFile) psiFile));
|
||||
}
|
||||
});
|
||||
psiDocManager.commitDocument(document);
|
||||
}
|
||||
}, this);
|
||||
|
||||
Editor editor = editorFactory.createEditor(document, project, JetFileType.INSTANCE, !editable);
|
||||
EditorSettings settings = editor.getSettings();
|
||||
settings.setVirtualSpace(false);
|
||||
settings.setLineMarkerAreaShown(false);
|
||||
settings.setFoldingOutlineShown(false);
|
||||
settings.setRightMarginShown(false);
|
||||
settings.setAdditionalPageAtBottom(false);
|
||||
settings.setAdditionalLinesCount(2);
|
||||
settings.setAdditionalColumnsCount(12);
|
||||
|
||||
assert editor instanceof EditorEx;
|
||||
((EditorEx)editor).setEmbeddedIntoDialogWrapper(true);
|
||||
|
||||
editor.getColorsScheme().setColor(EditorColors.CARET_ROW_COLOR, editor.getColorsScheme().getDefaultBackground());
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
private static int getLineY(@NotNull Editor editor, @NotNull PsiElement psiElementInEditor) {
|
||||
LogicalPosition logicalPosition = editor.offsetToLogicalPosition(psiElementInEditor.getTextOffset());
|
||||
return editor.logicalPositionToXY(logicalPosition).y;
|
||||
}
|
||||
|
||||
public void show(@Nullable Point point, @NotNull final Editor mainEditor, @NotNull PsiElement psiElementInEditor) {
|
||||
int lineY = getLineY(mainEditor, psiElementInEditor);
|
||||
EditorGutterComponentEx gutter = (EditorGutterComponentEx) mainEditor.getGutter();
|
||||
Point adjustedPoint;
|
||||
if (point == null) {
|
||||
adjustedPoint = new Point(gutter.getIconsAreaWidth() + gutter.getLineMarkerAreaOffset(), lineY);
|
||||
}
|
||||
else {
|
||||
adjustedPoint = new Point(point.x, Math.min(lineY, point.y));
|
||||
}
|
||||
balloon.show(new RelativePoint(gutter, adjustedPoint), Balloon.Position.above);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IdeFocusManager.getInstance(mainEditor.getProject()).requestFocus(editor.getContentComponent(), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
EditorFactory editorFactory = EditorFactory.getInstance();
|
||||
assert editorFactory != null;
|
||||
editorFactory.releaseEditor(editor);
|
||||
}
|
||||
|
||||
private void saveAndHide() {
|
||||
balloon.hide();
|
||||
|
||||
final String newSignature = editor.getDocument().getText();
|
||||
if (previousSignature.equals(newSignature)) {
|
||||
return;
|
||||
}
|
||||
|
||||
new WriteCommandAction(project) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
ExternalAnnotationsManager.getInstance(project).editExternalAnnotation(
|
||||
annotatedElement, kotlinSignatureAnnotationFqName,
|
||||
KotlinSignatureUtil.signatureToNameValuePairs(project, newSignature)
|
||||
);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private static boolean hasErrors(@NotNull JetFile file) {
|
||||
return AnalyzingUtils.getSyntaxErrorRanges(file).isEmpty();
|
||||
}
|
||||
|
||||
private class MyPanel extends JPanel {
|
||||
private final JButton saveButton;
|
||||
|
||||
MyPanel() {
|
||||
super(new BorderLayout());
|
||||
add(editor.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
if (editable) {
|
||||
JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
saveButton = new JButton("Save") {
|
||||
@Override
|
||||
public boolean isDefaultButton() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
toolbar.add(saveButton);
|
||||
add(toolbar, BorderLayout.SOUTH);
|
||||
|
||||
ActionListener saveAndHideListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull ActionEvent e) {
|
||||
saveAndHide();
|
||||
}
|
||||
};
|
||||
|
||||
saveButton.addActionListener(saveAndHideListener);
|
||||
registerKeyboardAction(saveAndHideListener, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
else {
|
||||
saveButton = null;
|
||||
}
|
||||
|
||||
registerKeyboardAction(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull ActionEvent e) {
|
||||
balloon.hide();
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
|
||||
void setSaveButtonEnabled(boolean enabled) {
|
||||
if (saveButton != null) {
|
||||
saveButton.setEnabled(enabled);
|
||||
saveButton.setToolTipText(enabled ? null : "Please fix errors in signature to save it.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-225
@@ -1,225 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsListener;
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.idea.JetBundle;
|
||||
import org.jetbrains.kotlin.idea.JetIcons;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaConstructorImpl;
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaFieldImpl;
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaMethodImpl;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions;
|
||||
import org.jetbrains.kotlin.renderer.NameShortness;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SIGNATURE;
|
||||
|
||||
public class KotlinSignatureAnnotationIntention extends BaseIntentionAction implements Iconable {
|
||||
private static final DescriptorRenderer RENDERER = DescriptorRenderer.Companion.withOptions(
|
||||
new Function1<DescriptorRendererOptions, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(DescriptorRendererOptions options) {
|
||||
options.setTypeNormalizer(IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES);
|
||||
options.setNameShortness(NameShortness.SHORT);
|
||||
options.setModifiers(Collections.<DescriptorRendererModifier>emptySet());
|
||||
options.setWithDefinedIn(false);
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return JetBundle.message("add.kotlin.signature.action.family.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(@IconFlags int flags) {
|
||||
return JetIcons.SMALL_LOGO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
PsiMember memberUnderCaret = findMemberUnderCaret(file, editor);
|
||||
if (memberUnderCaret == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiModifierListOwner annotationOwner = KotlinSignatureUtil.getAnalyzableAnnotationOwner(memberUnderCaret);
|
||||
if (annotationOwner == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(annotationOwner)) return false;
|
||||
|
||||
if (KotlinSignatureUtil.findKotlinSignatureAnnotation(annotationOwner) != null) {
|
||||
if (KotlinSignatureUtil.isAnnotationEditable(annotationOwner)) {
|
||||
setText(JetBundle.message("edit.kotlin.signature.action.text"));
|
||||
}
|
||||
else {
|
||||
setText(JetBundle.message("view.kotlin.signature.action.text"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
setText(JetBundle.message("add.kotlin.signature.action.text"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
final PsiMember annotatedElement = findMemberUnderCaret(file, editor);
|
||||
|
||||
assert annotatedElement != null;
|
||||
|
||||
if (KotlinSignatureUtil.findKotlinSignatureAnnotation(annotatedElement) != null) {
|
||||
EditSignatureAction.invokeEditSignature(annotatedElement, editor, null);
|
||||
return;
|
||||
}
|
||||
|
||||
String signature = getDefaultSignature(project, annotatedElement);
|
||||
|
||||
final MessageBusConnection busConnection = project.getMessageBus().connect();
|
||||
busConnection.subscribe(ExternalAnnotationsManager.TOPIC, new ExternalAnnotationsListener.Adapter() {
|
||||
@Override
|
||||
public void afterExternalAnnotationChanging(@NotNull PsiModifierListOwner owner, @NotNull String annotationFQName, boolean successful) {
|
||||
busConnection.disconnect();
|
||||
|
||||
if (successful && owner == annotatedElement && KOTLIN_SIGNATURE.asString().equals(annotationFQName)) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KotlinSignatureUtil.refreshMarkers(project);
|
||||
EditSignatureAction.invokeEditSignature(annotatedElement, editor, null);
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AddAnnotationFix addAnnotationFix = new AddAnnotationFix(
|
||||
KOTLIN_SIGNATURE.asString(), annotatedElement, KotlinSignatureUtil
|
||||
.signatureToNameValuePairs(annotatedElement.getProject(), signature));
|
||||
addAnnotationFix.invoke(project, editor, file);
|
||||
}
|
||||
|
||||
private static String renderMember(PsiMember member) {
|
||||
PsiClass containingClass = member.getContainingClass();
|
||||
assert containingClass != null;
|
||||
String qualifiedName = containingClass.getQualifiedName();
|
||||
assert qualifiedName != null;
|
||||
|
||||
return member.getName() + " in " + qualifiedName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDefaultSignature(@NotNull Project project, @NotNull PsiMember element) {
|
||||
PsiMember analyzableAnnotationOwner = KotlinSignatureUtil.getAnalyzableAnnotationOwner(element);
|
||||
assert analyzableAnnotationOwner != null;
|
||||
JavaDescriptorResolver javaDescriptorResolver = ResolvePackage.getJavaDescriptorResolver(analyzableAnnotationOwner);
|
||||
|
||||
if (analyzableAnnotationOwner instanceof PsiMethod) {
|
||||
PsiMethod psiMethod = (PsiMethod) analyzableAnnotationOwner;
|
||||
if (psiMethod.isConstructor()) {
|
||||
ConstructorDescriptor constructorDescriptor =
|
||||
ResolvePackage.resolveConstructor(javaDescriptorResolver, new JavaConstructorImpl(psiMethod));
|
||||
assert constructorDescriptor != null: "Couldn't find constructor descriptor for " + renderMember(psiMethod);
|
||||
return getDefaultConstructorAnnotation(constructorDescriptor);
|
||||
}
|
||||
else {
|
||||
FunctionDescriptor functionDescriptor = ResolvePackage.resolveMethod(javaDescriptorResolver, new JavaMethodImpl(psiMethod));
|
||||
assert functionDescriptor != null: "Couldn't find function descriptor for " + renderMember(psiMethod);
|
||||
return RENDERER.render(functionDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (analyzableAnnotationOwner instanceof PsiField) {
|
||||
VariableDescriptor variableDescriptor =
|
||||
ResolvePackage.resolveField(javaDescriptorResolver, new JavaFieldImpl((PsiField) analyzableAnnotationOwner));
|
||||
assert variableDescriptor != null : "Couldn't find variable descriptor for field " + renderMember(analyzableAnnotationOwner);
|
||||
return RENDERER.render(variableDescriptor);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("PsiMethod or PsiField are expected");
|
||||
}
|
||||
|
||||
private static String getDefaultConstructorAnnotation(ConstructorDescriptor constructorDescriptor) {
|
||||
return String.format("fun %s%s", constructorDescriptor.getContainingDeclaration().getName(), RENDERER.renderFunctionParameters(constructorDescriptor));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiMember findMemberUnderCaret(@NotNull PsiElement file, Editor editor) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiMember methodMember = findMethod(file, offset);
|
||||
if (methodMember != null) {
|
||||
return methodMember;
|
||||
}
|
||||
|
||||
return findField(file, offset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiMethod findMethod(@NotNull PsiElement file, int offset) {
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
PsiMethod res = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
|
||||
if (res == null) return null;
|
||||
|
||||
//Not available in method's body
|
||||
PsiCodeBlock body = res.getBody();
|
||||
if (body != null) {
|
||||
TextRange bodyRange = body.getTextRange();
|
||||
if (bodyRange != null && bodyRange.getStartOffset() <= offset) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiField findField(@NotNull PsiElement file, int offset) {
|
||||
return PsiTreeUtil.getParentOfType(file.findElementAt(offset), PsiField.class);
|
||||
}
|
||||
}
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerProvider;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.idea.JetIcons;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil;
|
||||
import org.jetbrains.kotlin.load.java.JavaBindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class KotlinSignatureInJavaMarkerProvider implements LineMarkerProvider {
|
||||
private static final String SHOW_MARKERS_PROPERTY = "kotlin.signature.markers.enabled";
|
||||
private static final Logger LOG = Logger.getInstance(KotlinSignatureInJavaMarkerProvider.class);
|
||||
|
||||
private static final GutterIconNavigationHandler<PsiModifierListOwner> NAVIGATION_HANDLER = new GutterIconNavigationHandler<PsiModifierListOwner>() {
|
||||
@Override
|
||||
public void navigate(MouseEvent e, PsiModifierListOwner element) {
|
||||
if (UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED)) {
|
||||
new EditSignatureAction(element).actionPerformed(DataManager.getInstance().getDataContext(e.getComponent()), e.getPoint());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
|
||||
if (elements.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiElement firstElement = elements.get(0);
|
||||
Project project = firstElement.getProject();
|
||||
if (!isMarkersEnabled(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ProjectStructureUtil.hasJvmKotlinModules(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(firstElement);
|
||||
if (module != null && !ProjectStructureUtil.isUsedInKotlinJavaModule(module)) {
|
||||
return;
|
||||
}
|
||||
|
||||
markElements(elements, result, firstElement.getContainingFile());
|
||||
}
|
||||
|
||||
private static void markElements(
|
||||
@NotNull List<PsiElement> elements,
|
||||
@NotNull Collection<LineMarkerInfo> result,
|
||||
@NotNull PsiFile psiFile
|
||||
) {
|
||||
try {
|
||||
for (PsiElement element : elements) {
|
||||
markElement(element, result);
|
||||
}
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
LOG.warn("Exception while collecting KotlinSignature markers:\n" + ExceptionUtil.getThrowableText(error));
|
||||
}
|
||||
}
|
||||
|
||||
private static void markElement(@NotNull PsiElement element, @NotNull Collection<LineMarkerInfo> result) {
|
||||
Project project = element.getProject();
|
||||
PsiModifierListOwner annotationOwner = KotlinSignatureUtil.getAnalyzableAnnotationOwner(element);
|
||||
if (!(annotationOwner instanceof PsiMember)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeclarationDescriptor memberDescriptor = ResolvePackage.getJavaMemberDescriptor((PsiMember) annotationOwner);
|
||||
|
||||
if (memberDescriptor == null) return;
|
||||
|
||||
BindingContext bindingContext = KotlinCacheService.getInstance(project).getGlobalFacade(JvmPlatform.INSTANCE$)
|
||||
.getFrontendService(annotationOwner, BindingTrace.class).getBindingContext();
|
||||
|
||||
List<String> errors = bindingContext.get(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, memberDescriptor);
|
||||
boolean hasSignatureAnnotation = KotlinSignatureUtil.findKotlinSignatureAnnotation(annotationOwner) != null;
|
||||
|
||||
if (errors != null || hasSignatureAnnotation) {
|
||||
result.add(new MyLineMarkerInfo((PsiModifierListOwner) element, errors, hasSignatureAnnotation));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMarkersEnabled(@NotNull Project project) {
|
||||
return PropertiesComponent.getInstance(project).getBoolean(SHOW_MARKERS_PROPERTY, true);
|
||||
}
|
||||
|
||||
public static void setMarkersEnabled(@NotNull Project project, boolean value) {
|
||||
PropertiesComponent.getInstance(project).setValue(SHOW_MARKERS_PROPERTY, Boolean.toString(value));
|
||||
KotlinSignatureUtil.refreshMarkers(project);
|
||||
}
|
||||
|
||||
private static class MyLineMarkerInfo extends LineMarkerInfo<PsiModifierListOwner> {
|
||||
public MyLineMarkerInfo(PsiModifierListOwner element, @Nullable List<String> errors, boolean hasAnnotation) {
|
||||
super(element, element.getTextOffset(), errors != null ? AllIcons.Ide.Error : JetIcons.SMALL_LOGO, Pass.UPDATE_OVERRIDEN_MARKERS,
|
||||
new TooltipProvider(errors), hasAnnotation ? NAVIGATION_HANDLER : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GutterIconRenderer createGutterRenderer() {
|
||||
return new LineMarkerGutterIconRenderer<PsiModifierListOwner>(this) {
|
||||
@Nullable
|
||||
@Override
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
if (getNavigationHandler() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiModifierListOwner element = getElement();
|
||||
assert element != null;
|
||||
|
||||
return new DefaultActionGroup(new EditSignatureAction(element), new DeleteSignatureAction(element));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static class TooltipProvider implements Function<PsiElement, String> {
|
||||
private final @Nullable List<String> errors;
|
||||
|
||||
private TooltipProvider(@Nullable List<String> errors) {
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String fun(PsiElement element) {
|
||||
PsiAnnotation annotation = KotlinSignatureUtil.findKotlinSignatureAnnotation(element);
|
||||
|
||||
if (annotation == null) return errorsString();
|
||||
|
||||
String signature = KotlinSignatureUtil.getKotlinSignature(annotation);
|
||||
String text = "Alternative Kotlin signature is available for this method:\n" + StringUtil.escapeXml(signature);
|
||||
if (errors == null) {
|
||||
return text;
|
||||
}
|
||||
return text + "\nIt has the following " + StringUtil.pluralize("error", errors.size()) + ":\n" + errorsString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String errorsString() {
|
||||
assert errors != null;
|
||||
return StringUtil.escapeXml(StringUtil.join(errors, "\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsListener;
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
public class KotlinSignatureInJavaMarkerUpdater extends AbstractProjectComponent {
|
||||
protected KotlinSignatureInJavaMarkerUpdater(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
myProject.getMessageBus().connect().subscribe(ExternalAnnotationsManager.TOPIC, new ExternalAnnotationsListener.Adapter() {
|
||||
@Override
|
||||
public void externalAnnotationsChangedExternally() {
|
||||
KotlinSignatureUtil.refreshMarkers(myProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.load.java.components.PsiBasedExternalAnnotationResolver;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SIGNATURE;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.OLD_KOTLIN_SIGNATURE;
|
||||
|
||||
class KotlinSignatureUtil {
|
||||
private KotlinSignatureUtil() {
|
||||
}
|
||||
|
||||
/* For element from library sources or decompiled library sources return corresponding cls element */
|
||||
@Nullable
|
||||
static PsiMember getAnalyzableAnnotationOwner(@NotNull PsiElement element) {
|
||||
if (!(element instanceof PsiField || element instanceof PsiMethod) || element instanceof PsiEnumConstant) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiMember member = (PsiMember) element;
|
||||
if (member.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiMember annotationOwner = element.getOriginalElement() instanceof PsiMember
|
||||
? (PsiMember) element.getOriginalElement()
|
||||
: (PsiMember) element;
|
||||
|
||||
if (!annotationOwner.isPhysical()) {
|
||||
// this is fake PsiFile which is mirror for ClsFile without sources
|
||||
PsiCompiledElement compiledElement = element.getUserData(ClsElementImpl.COMPILED_ELEMENT);
|
||||
if (compiledElement instanceof PsiMember) {
|
||||
return (PsiMember) compiledElement;
|
||||
}
|
||||
}
|
||||
return annotationOwner;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String getKotlinSignature(@NotNull PsiAnnotation kotlinSignatureAnnotation) {
|
||||
PsiNameValuePair pair = kotlinSignatureAnnotation.getParameterList().getAttributes()[0];
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
else if (value instanceof PsiLiteralExpression) {
|
||||
Object valueObject = ((PsiLiteralExpression) value).getValue();
|
||||
return valueObject == null ? "null" : StringUtil.unescapeStringCharacters(valueObject.toString());
|
||||
}
|
||||
else {
|
||||
return value.getText();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static PsiNameValuePair[] signatureToNameValuePairs(@NotNull Project project, @NotNull String signature) {
|
||||
return JavaPsiFacade.getElementFactory(project).createAnnotationFromText(
|
||||
"@" + KOTLIN_SIGNATURE + "(value=\"" + StringUtil.escapeStringCharacters(signature) + "\")", null)
|
||||
.getParameterList().getAttributes();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiAnnotation findKotlinSignatureAnnotation(@NotNull PsiElement element) {
|
||||
if (!(element instanceof PsiModifierListOwner)) return null;
|
||||
PsiModifierListOwner annotationOwner = getAnalyzableAnnotationOwner(element);
|
||||
if (annotationOwner == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiModifierList list = annotationOwner.getModifierList();
|
||||
PsiAnnotation annotation = list == null ? null : list.findAnnotation(KOTLIN_SIGNATURE.asString());
|
||||
if (annotation == null) {
|
||||
annotation = PsiBasedExternalAnnotationResolver.findExternalAnnotation(annotationOwner, KOTLIN_SIGNATURE);
|
||||
if (annotation == null) {
|
||||
annotation = list == null ? null : list.findAnnotation(OLD_KOTLIN_SIGNATURE.asString());
|
||||
if (annotation == null) {
|
||||
annotation = PsiBasedExternalAnnotationResolver.findExternalAnnotation(annotationOwner, OLD_KOTLIN_SIGNATURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (annotation == null) return null;
|
||||
if (annotation.getParameterList().getAttributes().length == 0) return null;
|
||||
return annotation;
|
||||
}
|
||||
|
||||
static void refreshMarkers(@NotNull Project project) {
|
||||
DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
}
|
||||
|
||||
static boolean isAnnotationEditable(@NotNull PsiElement element) {
|
||||
PsiModifierListOwner annotationOwner = getAnalyzableAnnotationOwner(element);
|
||||
if (annotationOwner == null) {
|
||||
return false;
|
||||
}
|
||||
PsiAnnotation annotation = findKotlinSignatureAnnotation(element);
|
||||
assert annotation != null : "Annotation not found for " + element.getText();
|
||||
if (annotation.getContainingFile() == annotationOwner.getContainingFile()) {
|
||||
return annotation.isWritable();
|
||||
} else {
|
||||
ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(element.getProject());
|
||||
//noinspection ConstantConditions
|
||||
return annotationsManager.isExternalAnnotationWritable(annotationOwner, annotation.getQualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.ktSignature;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
|
||||
public class ShowKotlinSignaturesAction extends ToggleAction {
|
||||
public ShowKotlinSignaturesAction() {
|
||||
super("Show Kotlin Signatures");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
return project != null && KotlinSignatureInJavaMarkerProvider.isMarkersEnabled(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
e.getPresentation().setVisible(false);
|
||||
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
|
||||
if (psiFile != null && psiFile.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
e.getPresentation().setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
Project project = e.getProject();
|
||||
assert project != null;
|
||||
KotlinSignatureInJavaMarkerProvider.setMarkersEnabled(project, state);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user