Converted to Kotlin

This commit is contained in:
Valentin Kipyatkov
2015-11-13 20:09:40 +03:00
parent dc60c62781
commit bfddba7789
13 changed files with 422 additions and 482 deletions
@@ -1,109 +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.liveTemplates.macro;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateEditingAdapter;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassKind;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler;
import org.jetbrains.kotlin.psi.KtReferenceExpression;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
class AnonymousTemplateEditingListener extends TemplateEditingAdapter {
private KtReferenceExpression classRef;
private ClassDescriptor classDescriptor;
private final Editor editor;
private final PsiFile psiFile;
private static final Key<AnonymousTemplateEditingListener> LISTENER_KEY = Key.create("kotlin.AnonymousTemplateEditingListener");
public AnonymousTemplateEditingListener(PsiFile psiFile, Editor editor) {
this.psiFile = psiFile;
this.editor = editor;
}
@Override
public void currentVariableChanged(TemplateState templateState, Template template, int oldIndex, int newIndex) {
assert templateState.getTemplate() != null;
TextRange variableRange = templateState.getVariableRange("SUPERTYPE");
if (variableRange == null) return;
PsiElement name = psiFile.findElementAt(variableRange.getStartOffset());
if (name != null && name.getParent() instanceof KtReferenceExpression) {
KtReferenceExpression ref = (KtReferenceExpression) name.getParent();
DeclarationDescriptor descriptor = ResolutionUtils.analyze(ref, BodyResolveMode.FULL).get(BindingContext.REFERENCE_TARGET, ref);
if (descriptor instanceof ClassDescriptor) {
classRef = ref;
classDescriptor = (ClassDescriptor) descriptor;
}
}
}
@Override
public void templateFinished(Template template, boolean brokenOff) {
editor.putUserData(LISTENER_KEY, null);
if (brokenOff) {
return;
}
if (classDescriptor != null) {
if (classDescriptor.getKind() == ClassKind.CLASS) {
int placeToInsert = classRef.getTextRange().getEndOffset();
PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile).insertString(placeToInsert, "()");
boolean hasConstructorsParameters = false;
for (ConstructorDescriptor cd : classDescriptor.getConstructors()) {
// TODO check for visibility
hasConstructorsParameters |= cd.getValueParameters().size() != 0;
}
if (hasConstructorsParameters) {
editor.getCaretModel().moveToOffset(placeToInsert + 1);
}
}
new ImplementMembersHandler().invoke(psiFile.getProject(), editor, psiFile, true);
}
}
static void registerListener(Editor editor, Project project) {
if (editor.getUserData(LISTENER_KEY) != null) {
return;
}
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
assert psiFile != null;
TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
if (templateState != null) {
AnonymousTemplateEditingListener listener = new AnonymousTemplateEditingListener(psiFile, editor);
editor.putUserData(LISTENER_KEY, listener);
templateState.addTemplateStateListener(listener);
}
}
}
@@ -0,0 +1,96 @@
/*
* 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.liveTemplates.macro
import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.TemplateEditingAdapter
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateState
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
internal class AnonymousTemplateEditingListener(private val psiFile: PsiFile, private val editor: Editor) : TemplateEditingAdapter() {
private var classRef: KtReferenceExpression? = null
private var classDescriptor: ClassDescriptor? = null
override fun currentVariableChanged(templateState: TemplateState?, template: Template?, oldIndex: Int, newIndex: Int) {
assert(templateState!!.template != null)
val variableRange = templateState.getVariableRange("SUPERTYPE") ?: return
val name = psiFile.findElementAt(variableRange.startOffset)
if (name != null && name.parent is KtReferenceExpression) {
val ref = name.parent as KtReferenceExpression
val descriptor = ref.analyze(BodyResolveMode.FULL).get(BindingContext.REFERENCE_TARGET, ref)
if (descriptor is ClassDescriptor) {
classRef = ref
classDescriptor = descriptor
}
}
}
override fun templateFinished(template: Template?, brokenOff: Boolean) {
editor.putUserData(LISTENER_KEY, null)
if (brokenOff) {
return
}
if (classDescriptor != null) {
if (classDescriptor!!.kind == ClassKind.CLASS) {
val placeToInsert = classRef!!.textRange.endOffset
PsiDocumentManager.getInstance(psiFile.project).getDocument(psiFile)!!.insertString(placeToInsert, "()")
var hasConstructorsParameters = false
for (cd in classDescriptor!!.constructors) {
// TODO check for visibility
hasConstructorsParameters = hasConstructorsParameters or (cd.valueParameters.size != 0)
}
if (hasConstructorsParameters) {
editor.caretModel.moveToOffset(placeToInsert + 1)
}
}
ImplementMembersHandler().invoke(psiFile.project, editor, psiFile, true)
}
}
companion object {
private val LISTENER_KEY = Key.create<AnonymousTemplateEditingListener>("kotlin.AnonymousTemplateEditingListener")
fun registerListener(editor: Editor, project: Project) {
if (editor.getUserData(LISTENER_KEY) != null) return
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.document)!!
val templateState = TemplateManagerImpl.getTemplateState(editor)
if (templateState != null) {
val listener = AnonymousTemplateEditingListener(psiFile, editor)
editor.putUserData(LISTENER_KEY, listener)
templateState.addTemplateStateListener(listener)
}
}
}
}
@@ -1,44 +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.liveTemplates.macro;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.core.IterableTypesDetector;
public class AnyVariableMacro extends BaseKotlinVariableMacro {
@Override
public String getName() {
return "kotlinVariable";
}
@Override
public String getPresentableName() {
return KotlinBundle.message("macro.variable.of.type");
}
@Override
protected boolean isSuitable(
@NotNull VariableDescriptor variableDescriptor,
@NotNull Project project,
@NotNull IterableTypesDetector iterableTypesDetector
) {
return true;
}
}
@@ -0,0 +1,39 @@
/*
* 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.liveTemplates.macro
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
class AnyVariableMacro : BaseKotlinVariableMacro() {
override fun getName(): String {
return "kotlinVariable"
}
override fun getPresentableName(): String {
return KotlinBundle.message("macro.variable.of.type")
}
override fun isSuitable(
variableDescriptor: VariableDescriptor,
project: Project,
iterableTypesDetector: IterableTypesDetector): Boolean {
return true
}
}
@@ -1,154 +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.liveTemplates.macro;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.codeInsight.template.Macro;
import com.intellij.codeInsight.template.Result;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.idea.core.IterableTypesDetection;
import org.jetbrains.kotlin.idea.core.IterableTypesDetector;
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade;
import org.jetbrains.kotlin.idea.util.ExtensionUtils;
import org.jetbrains.kotlin.idea.util.ScopeUtils;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
import java.util.*;
public abstract class BaseKotlinVariableMacro extends Macro {
@Nullable
private KtNamedDeclaration[] getVariables(Expression[] params, ExpressionContext context) {
if (params.length != 0) return null;
Project project = context.getProject();
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument());
if (!(psiFile instanceof KtFile)) return null;
KtExpression contextExpression = findContextExpression(psiFile, context.getStartOffset());
if (contextExpression == null) return null;
ResolutionFacade resolutionFacade = ResolutionUtils.getResolutionFacade(contextExpression);
BindingContext bindingContext = resolutionFacade.analyze(contextExpression, BodyResolveMode.FULL);
LexicalScope scope = ScopeUtils.getResolutionScope(contextExpression, bindingContext, resolutionFacade);
IterableTypesDetector detector = resolutionFacade.getIdeService(IterableTypesDetection.class).createDetector(scope);
DataFlowInfo dataFlowInfo = BindingContextUtilsKt.getDataFlowInfo(bindingContext, contextExpression);
List<VariableDescriptor> filteredDescriptors = new ArrayList<VariableDescriptor>();
for (DeclarationDescriptor declarationDescriptor : getAllVariables(scope)) {
if (declarationDescriptor instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor;
if (variableDescriptor.getExtensionReceiverParameter() != null
&& ExtensionUtils.substituteExtensionIfCallableWithImplicitReceiver(
variableDescriptor, scope, bindingContext, dataFlowInfo).isEmpty()) {
continue;
}
if (isSuitable(variableDescriptor, project, detector)) {
filteredDescriptors.add(variableDescriptor);
}
}
}
List<KtNamedDeclaration> declarations = new ArrayList<KtNamedDeclaration>();
for (DeclarationDescriptor declarationDescriptor : filteredDescriptors) {
PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor);
assert declaration == null || declaration instanceof PsiNamedElement;
if (declaration instanceof KtProperty || declaration instanceof KtParameter) {
declarations.add((KtNamedDeclaration) declaration);
}
}
return declarations.toArray(new KtNamedDeclaration[declarations.size()]);
}
private static Collection<DeclarationDescriptor> getAllVariables(LexicalScope scope) {
Collection<DeclarationDescriptor> result = ContainerUtil.newArrayList();
result.addAll(ScopeUtilsKt.collectDescriptorsFiltered(scope, DescriptorKindFilter.VARIABLES, MemberScope.Companion.getALL_NAME_FILTER()));
for (ReceiverParameterDescriptor implicitReceiver : ScopeUtilsKt.getImplicitReceiversHierarchy(scope)) {
result.addAll(DescriptorUtils.getAllDescriptors(implicitReceiver.getType().getMemberScope()));
}
return result;
}
protected abstract boolean isSuitable(
@NotNull VariableDescriptor variableDescriptor,
@NotNull Project project,
@NotNull IterableTypesDetector iterableTypesDetector
);
@Nullable
private static KtExpression findContextExpression(PsiFile psiFile, int startOffset) {
PsiElement e = psiFile.findElementAt(startOffset);
while (e != null) {
if (e instanceof KtExpression) {
return (KtExpression) e;
}
e = e.getParent();
}
return null;
}
@Override
public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
KtNamedDeclaration[] vars = getVariables(params, context);
if (vars == null || vars.length == 0) return null;
return new KotlinPsiElementResult(vars[0]);
}
@Override
public LookupElement[] calculateLookupItems(@NotNull Expression[] params, ExpressionContext context) {
PsiNamedElement[] vars = getVariables(params, context);
if (vars == null || vars.length < 2) return null;
Set<LookupElement> set = new LinkedHashSet<LookupElement>();
for (PsiNamedElement var : vars) {
set.add(LookupElementBuilder.create(var));
}
return set.toArray(new LookupElement[set.size()]);
}
}
@@ -0,0 +1,141 @@
/*
* 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.liveTemplates.macro
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.codeInsight.template.Expression
import com.intellij.codeInsight.template.ExpressionContext
import com.intellij.codeInsight.template.Macro
import com.intellij.codeInsight.template.Result
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiNamedElement
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.IterableTypesDetection
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallableWithImplicitReceiver
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import java.util.*
abstract class BaseKotlinVariableMacro : Macro() {
private fun getVariables(params: Array<Expression>, context: ExpressionContext): Array<KtNamedDeclaration>? {
if (params.size != 0) return null
val project = context.project
PsiDocumentManager.getInstance(project).commitAllDocuments()
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(context.editor!!.document)
if (psiFile !is KtFile) return null
val contextExpression = findContextExpression(psiFile, context.startOffset) ?: return null
val resolutionFacade = contextExpression.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(contextExpression, BodyResolveMode.FULL)
val scope = contextExpression.getResolutionScope(bindingContext, resolutionFacade)
val detector = resolutionFacade.getIdeService(IterableTypesDetection::class.java).createDetector(scope)
val dataFlowInfo = bindingContext.getDataFlowInfo(contextExpression)
val filteredDescriptors = ArrayList<VariableDescriptor>()
for (declarationDescriptor in getAllVariables(scope)) {
if (declarationDescriptor is VariableDescriptor) {
if (declarationDescriptor.extensionReceiverParameter != null && declarationDescriptor.substituteExtensionIfCallableWithImplicitReceiver(scope, bindingContext, dataFlowInfo).isEmpty()) {
continue
}
if (isSuitable(declarationDescriptor, project, detector)) {
filteredDescriptors.add(declarationDescriptor)
}
}
}
val declarations = ArrayList<KtNamedDeclaration>()
for (declarationDescriptor in filteredDescriptors) {
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor)
assert(declaration == null || declaration is PsiNamedElement)
if (declaration is KtProperty) {
declarations.add(declaration)
}
else if (declaration is KtParameter) {
declarations.add(declaration)
}
}
return declarations.toTypedArray()
}
private fun getAllVariables(scope: LexicalScope): Collection<DeclarationDescriptor> {
val result = ContainerUtil.newArrayList<DeclarationDescriptor>()
result.addAll(scope.collectDescriptorsFiltered(DescriptorKindFilter.VARIABLES, MemberScope.ALL_NAME_FILTER))
for (implicitReceiver in scope.getImplicitReceiversHierarchy()) {
result.addAll(DescriptorUtils.getAllDescriptors(implicitReceiver.type.memberScope))
}
return result
}
protected abstract fun isSuitable(
variableDescriptor: VariableDescriptor,
project: Project,
iterableTypesDetector: IterableTypesDetector): Boolean
private fun findContextExpression(psiFile: PsiFile, startOffset: Int): KtExpression? {
var e = psiFile.findElementAt(startOffset)
while (e != null) {
if (e is KtExpression) {
return e
}
e = e.parent
}
return null
}
override fun calculateResult(params: Array<Expression>, context: ExpressionContext): Result? {
val vars = getVariables(params, context)
if (vars == null || vars.size == 0) return null
return KotlinPsiElementResult(vars[0])
}
override fun calculateLookupItems(params: Array<Expression>, context: ExpressionContext): Array<LookupElement>? {
val vars = getVariables(params, context)
if (vars == null || vars.size < 2) return null
val set = LinkedHashSet<LookupElement>()
for (`var` in vars) {
set.add(LookupElementBuilder.create(`var`))
}
return set.toArray<LookupElement>(arrayOfNulls<LookupElement>(set.size))
}
}
@@ -1,74 +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.liveTemplates.macro;
import com.intellij.codeInsight.template.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.psi.KtFunction;
import org.jetbrains.kotlin.psi.KtParameter;
import java.util.ArrayList;
import java.util.List;
public class FunctionParametersMacro extends Macro {
@Override
public String getName() {
return "functionParameters";
}
@Override
public String getPresentableName() {
return KotlinBundle.message("macro.fun.parameters");
}
@Override
public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
Project project = context.getProject();
int templateStartOffset = context.getTemplateStartOffset();
int offset = templateStartOffset > 0 ? context.getTemplateStartOffset() - 1 : context.getTemplateStartOffset();
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument());
if (file == null) return null;
PsiElement place = file.findElementAt(offset);
while (place != null){
if (place instanceof KtFunction) {
List<Result> result = new ArrayList<Result>();
for (KtParameter param : ((KtFunction) place).getValueParameters()) {
String name = param.getName();
assert name != null;
result.add(new TextResult(name));
}
return new ListResult(result);
}
place = place.getParent();
}
return null;
}
@Override
public boolean isAcceptableInContext(TemplateContextType context) {
return context instanceof JavaCodeContextType;
}
}
@@ -0,0 +1,60 @@
/*
* 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.liveTemplates.macro
import com.intellij.codeInsight.template.*
import com.intellij.psi.PsiDocumentManager
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.psi.KtFunction
import java.util.*
class FunctionParametersMacro : Macro() {
override fun getName(): String {
return "functionParameters"
}
override fun getPresentableName(): String {
return KotlinBundle.message("macro.fun.parameters")
}
override fun calculateResult(params: Array<Expression>, context: ExpressionContext): Result? {
val project = context.project
val templateStartOffset = context.templateStartOffset
val offset = if (templateStartOffset > 0) context.templateStartOffset - 1 else context.templateStartOffset
PsiDocumentManager.getInstance(project).commitAllDocuments()
val file = PsiDocumentManager.getInstance(project).getPsiFile(context.editor!!.document) ?: return null
var place = file.findElementAt(offset)
while (place != null) {
if (place is KtFunction) {
val result = ArrayList<Result>()
for (param in place.valueParameters) {
result.add(TextResult(param.name!!))
}
return ListResult(result)
}
place = place.parent
}
return null
}
override fun isAcceptableInContext(context: TemplateContextType?): Boolean {
return context is JavaCodeContextType
}
}
@@ -1,46 +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.liveTemplates.macro;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.core.IterableTypesDetector;
public class IterableVariableMacro extends BaseKotlinVariableMacro {
@Override
public String getName() {
return "kotlinIterableVariable";
}
@Override
public String getPresentableName() {
return KotlinBundle.message("macro.iterable.variable");
}
@Override
protected boolean isSuitable(
@NotNull VariableDescriptor variableDescriptor,
@NotNull Project project,
@NotNull IterableTypesDetector iterableTypesDetector
) {
//TODO: smart-casts
return iterableTypesDetector.isIterable(variableDescriptor.getType(), null);
}
}
@@ -0,0 +1,41 @@
/*
* 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.liveTemplates.macro
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
class IterableVariableMacro : BaseKotlinVariableMacro() {
override fun getName(): String {
return "kotlinIterableVariable"
}
override fun getPresentableName(): String {
return KotlinBundle.message("macro.iterable.variable")
}
override fun isSuitable(
variableDescriptor: VariableDescriptor,
project: Project,
iterableTypesDetector: IterableTypesDetector): Boolean {
//TODO: smart-casts
return iterableTypesDetector.isIterable(variableDescriptor.type, null)
}
}
@@ -14,18 +14,13 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.liveTemplates.macro;
package org.jetbrains.kotlin.idea.liveTemplates.macro
import com.intellij.codeInsight.template.JavaPsiElementResult;
import com.intellij.psi.PsiNamedElement;
import com.intellij.codeInsight.template.JavaPsiElementResult
import com.intellij.psi.PsiNamedElement
public class KotlinPsiElementResult extends JavaPsiElementResult {
public KotlinPsiElementResult(PsiNamedElement element) {
super(element);
}
@Override
public String toString() {
return ((PsiNamedElement) getElement()).getName();
class KotlinPsiElementResult(element: PsiNamedElement) : JavaPsiElementResult(element) {
override fun toString(): String {
return (element as PsiNamedElement).name ?: ""
}
}
@@ -1,44 +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.liveTemplates.macro;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.core.IterableTypesDetector;
public class SuggestVariableNameMacro extends BaseKotlinVariableMacro {
@Override
public String getName() {
return "kotlinSuggestVariableName";
}
@Override
public String getPresentableName() {
return KotlinBundle.message("macro.suggest.variable.name");
}
@Override
protected boolean isSuitable(
@NotNull VariableDescriptor variableDescriptor,
@NotNull Project project,
@NotNull IterableTypesDetector iterableTypesDetector
) {
return variableDescriptor.getType().isMarkedNullable();
}
}
@@ -0,0 +1,39 @@
/*
* 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.liveTemplates.macro
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
class SuggestVariableNameMacro : BaseKotlinVariableMacro() {
override fun getName(): String {
return "kotlinSuggestVariableName"
}
override fun getPresentableName(): String {
return KotlinBundle.message("macro.suggest.variable.name")
}
override fun isSuitable(
variableDescriptor: VariableDescriptor,
project: Project,
iterableTypesDetector: IterableTypesDetector): Boolean {
return variableDescriptor.type.isMarkedNullable
}
}