/*
* 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.core.navigation;
import com.intellij.navigation.GotoClassContributor;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.project.Project;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.progress.EmptyProgressMonitor;
import jetbrains.mps.smodel.ModelAccessHelper;
import jetbrains.mps.util.Computable;
import jetbrains.mps.util.ConditionalIterable;
import jetbrains.mps.util.IterableUtil;
import jetbrains.mps.workbench.goTo.navigation.GotoNavigationUtil;
import jetbrains.mps.workbench.goTo.navigation.RootNodeElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.module.SearchScope;
import org.jetbrains.mps.openapi.persistence.NavigationParticipant.NavigationTarget;
import org.jetbrains.mps.openapi.persistence.NavigationParticipant.TargetKind;
import org.jetbrains.mps.util.Condition;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
/**
* This is a contributor into GoToClass action, which uses our GotoNavigationUtil to find nodes potentially
* quickly. In particular, for model files RootNodeNameIndex is used.
*
* This class is used instead of GoToClassMPSContributor, which was registered in MPSCore.xml but since some time
* didn't seem to be used in MPS at all. (GotoClassAction wasn't invoked, but GoToRootNode action was)
* That contributor however was picked up in idea when mps plugin was installed, and worked slowly, as it didn't use
* index, instead it just traversed all models and all roots.
*
* GoToClassContributor deleted in this commit.
*
* Created by danilla on 26/05/16.
*/
public class MPSIdeaGotoClassContributor implements GotoClassContributor {
private final static String SEPARATOR = ".";
@NotNull
@Override
public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
jetbrains.mps.project.Project mpsProject = ProjectHelper.fromIdeaProject(project);
if (mpsProject == null) {
return NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY;
}
SearchScope scope = includeNonProjectItems ? new ProperModelsGlobalSearchScope() : new ProperModelsProjectSearchScope(project);
Condition<NavigationItem> rightName = new Condition<NavigationItem>() {
@Override
public boolean met(NavigationItem item) {
return name.equals(item.getName());
}
};
List<NavigationItem> items = new ModelAccessHelper(mpsProject.getModelAccess()).runReadAction(new Computable<List<NavigationItem>>() {
@Override
public List<NavigationItem> compute() {
Collection<NavigationTarget> targets = GotoNavigationUtil.getNavigationTargets(TargetKind.ROOT, scope, new EmptyProgressMonitor());
NavigationItem[] items = new NavigationItem[targets.size()];
int i = 0;
for (NavigationTarget target : targets) {
items[i++] = new RootNodeElement(mpsProject, target);
}
return Arrays.asList(items);
}
});
Iterable<NavigationItem> itemsFilteredByName = name == null ? items : new ConditionalIterable<>(items, rightName);
return IterableUtil.asList(itemsFilteredByName).toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY);
}
@NotNull
@Override
public String[] getNames(Project project, boolean includeNonProjectItems) {
LinkedHashSet<String> rv = new LinkedHashSet<String>();
for (NavigationItem item : getItemsByName(null, null, project, includeNonProjectItems)) {
rv.add(item.getName());
}
return rv.toArray(new String[rv.size()]);
}
@Override
public String getQualifiedName(NavigationItem item) {
if (!(item instanceof RootNodeElement)) {
return null;
};
SModelReference modelRef = ((RootNodeElement) item).getModel();
String modelName = modelRef.getModelName();
return modelName + getQualifiedNameSeparator() + item.getName();
}
@Nullable
@Override
public String getQualifiedNameSeparator() {
return SEPARATOR;
}
}