/* * Copyright 2000-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 com.jetbrains.lang.dart.ide.actions; import com.google.common.collect.Lists; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator; import com.intellij.ide.util.DefaultPsiElementCellRenderer; import com.intellij.lang.LanguageCodeInsightActionHandler; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.lang.dart.DartBundle; import com.jetbrains.lang.dart.DartLanguage; import com.jetbrains.lang.dart.analyzer.DartAnalysisServerService; import com.jetbrains.lang.dart.ide.hierarchy.DartHierarchyUtil; import com.jetbrains.lang.dart.psi.DartClass; import com.jetbrains.lang.dart.psi.DartComponent; import com.jetbrains.lang.dart.util.DartResolveUtil; import org.dartlang.analysis.server.protocol.Element; import org.dartlang.analysis.server.protocol.ElementKind; import org.dartlang.analysis.server.protocol.Location; import org.dartlang.analysis.server.protocol.TypeHierarchyItem; import org.jetbrains.annotations.NotNull; import java.util.List; public class DartServerGotoSuperHandler implements LanguageCodeInsightActionHandler { @Override public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { final PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); final DartComponent inComponent = PsiTreeUtil.getParentOfType(at, DartComponent.class); final DartComponent inClass = PsiTreeUtil.getParentOfType(at, DartClass.class); if (inClass == null || inComponent == null || inComponent.getComponentName() == null) { return; } final boolean isInClass = inComponent instanceof DartClass; // ask for the super type hierarchy final VirtualFile virtualFile = file.getVirtualFile(); final int offset = inComponent.getComponentName().getTextRange().getStartOffset(); final List<TypeHierarchyItem> items = DartAnalysisServerService.getInstance(project).search_getTypeHierarchy(virtualFile, offset, true); // build list of DartComponent(s) final List<DartComponent> supers = Lists.newArrayList(); if (!items.isEmpty()) { TypeHierarchyItem seed = items.get(0); { final Integer superIndex = seed.getSuperclass(); if (superIndex != null) { final TypeHierarchyItem superItem = items.get(superIndex); addSuperComponent(project, supers, isInClass, superItem); } } for (int superIndex : seed.getMixins()) { final TypeHierarchyItem superItem = items.get(superIndex); addSuperComponent(project, supers, isInClass, superItem); } for (int superIndex : seed.getInterfaces()) { final TypeHierarchyItem superItem = items.get(superIndex); addSuperComponent(project, supers, isInClass, superItem); } } // prepare the title final String title; if (isInClass) { title = DartBundle.message("goto.super.class.chooser.title"); } else { title = CodeInsightBundle.message("goto.super.method.chooser.title"); } // open DartComponent(s) final NavigatablePsiElement[] targets = DartResolveUtil.getComponentNameArray(supers); PsiElementListNavigator.openTargets(editor, targets, title, null, new DefaultPsiElementCellRenderer()); } @Override public boolean isValidFor(Editor editor, PsiFile file) { return file.getLanguage() == DartLanguage.INSTANCE; } @Override public boolean startInWriteAction() { return false; } private static void addSuperComponent(@NotNull Project project, List<DartComponent> supers, boolean isInClass, TypeHierarchyItem item) { // prepare Element for the current item final Element itemElement = isInClass ? item.getClassElement() : item.getMemberElement(); if (itemElement == null) { return; } // ignore Object if (ElementKind.CLASS.equals(itemElement.getKind()) && "Object".equals(itemElement.getName())) { return; } // find the DartComponent final Location itemLocation = itemElement.getLocation(); final DartComponent itemComponent = DartHierarchyUtil.findDartComponent(project, itemLocation); if (itemComponent != null) { supers.add(itemComponent); } } }