/* * Copyright 2003-2016 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 jetbrains.mps.idea.java.usages; import com.intellij.find.findUsages.FindUsagesHandler; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Segment; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.usageView.UsageInfo; import com.intellij.util.Processor; import jetbrains.mps.ide.findusages.view.FindUtils; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.idea.core.psi.impl.MPSPsiNode; import jetbrains.mps.idea.core.psi.impl.MPSPsiProvider; import jetbrains.mps.idea.core.usages.IdeaSearchScope; import jetbrains.mps.progress.EmptyProgressMonitor; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.util.Computable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.module.SModuleReference; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import java.util.List; /** * This handler is returned for our MPS PSI nodes. * When FindUsages is invoked, Idea understands what mps psi element we're standing at * (out NodeEditor tells that) and invokes this handler with that element. * @see MPSFindUsagesHandlerFactory * @see jetbrains.mps.idea.core.editor.IdeaNodeEditor * danilla 5/16/13 */ public class MPSFindUsagesHandler extends FindUsagesHandler { protected MPSFindUsagesHandler(@NotNull PsiElement psiElement) { super(psiElement); } @Override public boolean processElementUsages(@NotNull final PsiElement element, @NotNull final Processor<UsageInfo> processor, @NotNull final FindUsagesOptions options) { final Project project = element.getProject(); final SearchScope scope = options.searchScope; final SRepository repository = ProjectHelper.getProjectRepository(element.getProject()); assert element instanceof MPSPsiNode; assert scope instanceof GlobalSearchScope; boolean cont = new ModelAccessHelper(repository.getModelAccess()).runReadAction(new Computable<Boolean>() { public Boolean compute() { String nodeUsageFinder = "jetbrains.mps.lang.structure.findUsages.NodeUsages_Finder"; SNode node = ((MPSPsiNode) element).getSNodeReference().resolve(repository); IdeaSearchScope ideaSearchScope = new IdeaSearchScope((GlobalSearchScope) scope); List<SNode> results = FindUtils.executeFinder(nodeUsageFinder, node, ideaSearchScope, new EmptyProgressMonitor()); for (SNode usageNode : results) { PsiElement mpsNode = MPSPsiProvider.getInstance(project).getPsi(usageNode); UsageInfo usage = new MPSUsageInfo((MPSPsiNode) mpsNode); if (!processor.process(usage)) { return false; } } return true; } }); // now process out-of-mps-models usages if (cont) { return super.processElementUsages(element, processor, options); } else { return false; } } } class MPSUsageInfo extends UsageInfo { MPSPsiNode myNode; public MPSUsageInfo(@NotNull MPSPsiNode element) { super(element); myNode = element; } @Nullable @Override public Segment getSegment() { return myNode.getTextRange(); } }