Commit 722a3841 authored by Alexander Bubenchikov's avatar Alexander Bubenchikov
Browse files

IDEA-197739 -introducing maven online autocompletion without using indices

parent 8532b20e
Showing with 601 additions and 378 deletions
+601 -378
......@@ -32,7 +32,7 @@ import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.indices.MavenIndex;
import org.jetbrains.idea.maven.indices.MavenSearchIndex;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.model.MavenRemoteRepository;
import org.jetbrains.plugins.gradle.util.GradleConstants;
......@@ -127,7 +127,7 @@ class ImportMavenRepositoriesTask {
.filter(index -> index.getUpdateTimestamp() == -1 &&
index.getFailureMessage() == null &&
MavenRepositoriesHolder.getInstance(myProject).contains(index.getRepositoryPathOrUrl()))
.map(MavenIndex::getRepositoryPathOrUrl)
.map(MavenSearchIndex::getRepositoryPathOrUrl)
.collect(Collectors.toList());
MavenRepositoriesHolder.getInstance(myProject).updateNotIndexedUrls(repositoriesWithEmptyIndex);
});
......
......@@ -17,6 +17,7 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.indices.MavenSearchIndex;
import org.jetbrains.idea.maven.indices.MavenIndex;
import org.jetbrains.idea.maven.indices.MavenIndicesManager;
import org.jetbrains.idea.maven.model.MavenRemoteRepository;
......@@ -69,7 +70,7 @@ public class MavenRepositoriesHolder {
if (notificationManager.isNotificationActive(NOTIFICATION_KEY)) return;
final MavenIndicesManager indicesManager = MavenIndicesManager.getInstance();
for (MavenIndex index : indicesManager.getIndices()) {
for (MavenSearchIndex index : indicesManager.getIndices()) {
if (indicesManager.getUpdatingState(index) != IDLE) return;
}
......@@ -87,7 +88,7 @@ public class MavenRepositoriesHolder {
ContainerUtil.filter(indicesManager.getIndices(), index -> isNotIndexed(index.getRepositoryPathOrUrl()));
indicesManager.scheduleUpdate(myProject, notIndexed).onSuccess(aVoid -> {
if (myNotIndexedUrls.isEmpty()) return;
for (MavenIndex index : notIndexed) {
for (MavenSearchIndex index : notIndexed) {
if (index.getUpdateTimestamp() != -1 || index.getFailureMessage() != null) {
myNotIndexedUrls.remove(index.getRepositoryPathOrUrl());
}
......
......@@ -4,10 +4,10 @@ package org.jetbrains.idea.maven.dom.converters;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.OffsetKey;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
......@@ -23,10 +23,12 @@ import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.project.MavenProject;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
public class MavenArtifactCoordinatesArtifactIdConverter extends MavenArtifactCoordinatesConverter {
@Override
......@@ -58,9 +60,9 @@ public class MavenArtifactCoordinatesArtifactIdConverter extends MavenArtifactCo
}
@Override
protected Set<String> doGetVariants(MavenId id, MavenProjectIndicesManager manager) {
protected Set<String> doGetVariants(MavenId id, DependencySearchService searchService) {
if (StringUtil.isEmptyOrSpaces(id.getGroupId())) return Collections.emptySet();
return manager.getArtifactIds(id.getGroupId());
return searchService.findArtifactCandidates(id).stream().map(s -> s.getArtifactId()).collect(Collectors.toSet());
}
private static class MavenArtifactInsertHandler implements InsertHandler<LookupElement> {
......@@ -76,7 +78,7 @@ public class MavenArtifactCoordinatesArtifactIdConverter extends MavenArtifactCo
context.commitDocument();
PsiFile contextFile = context.getFile();
if(!(contextFile instanceof XmlFile)) return;
if (!(contextFile instanceof XmlFile)) return;
XmlFile xmlFile = (XmlFile)contextFile;
......@@ -91,50 +93,27 @@ public class MavenArtifactCoordinatesArtifactIdConverter extends MavenArtifactCo
MavenDomDependency dependency = (MavenDomDependency)domElement;
String artifactId = item.getLookupString();
MavenId id = new MavenId(item.getLookupString());
String artifactId = id.getArtifactId();
String groupId = dependency.getGroupId().getStringValue();
OffsetKey startRef = context.trackOffset(context.getStartOffset(), false);
int len = context.getTailOffset() - context.getStartOffset();
if (StringUtil.isEmpty(groupId)) {
String g = getUniqueGroupIdOrNull(context.getProject(), artifactId);
if (g != null) {
dependency.getGroupId().setStringValue(g);
groupId = g;
}
else {
if (groupId == null) {
dependency.getGroupId().setStringValue("");
}
XmlTag groupIdTag = dependency.getGroupId().getXmlTag();
context.getEditor().getCaretModel().moveToOffset(groupIdTag.getValue().getTextRange().getStartOffset());
MavenDependencyCompletionUtil.invokeCompletion(context, CompletionType.SMART);
return;
groupId = id.getGroupId();
if (StringUtil.isEmpty(groupId)) {
dependency.getGroupId().setStringValue("");
}
XmlTag groupIdTag = dependency.getGroupId().getXmlTag();
context.getEditor().getCaretModel().moveToOffset(groupIdTag.getValue().getTextRange().getStartOffset());
MavenDependencyCompletionUtil.invokeCompletion(context, CompletionType.SMART);
return;
}
int offset = context.getOffset(startRef);
context.getDocument().replaceString(offset, offset + len, artifactId);
context.commitDocument();
MavenDependencyCompletionUtil.addTypeAndClassifierAndVersion(context, dependency, groupId, artifactId);
}
private static String getUniqueGroupIdOrNull(@NotNull Project project, @NotNull String artifactId) {
MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(project);
String res = null;
for (String groupId : manager.getGroupIds()) {
if (manager.getArtifactIds(groupId).contains(artifactId)) {
if (res == null) {
res = groupId;
}
else {
return null; // There are more then one appropriate groupId.
}
}
}
return res;
}
}
}
......@@ -26,7 +26,10 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.xml.*;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.ResolvingConverter;
import com.intellij.util.xml.impl.GenericDomValueReference;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
......@@ -40,6 +43,7 @@ import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.model.MavenPlugin;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
......@@ -69,15 +73,15 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert
@Override
@NotNull
public Collection<String> getVariants(ConvertContext context) {
MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(context.getProject());
DependencySearchService searchService = MavenProjectIndicesManager.getInstance(context.getProject()).getSearchService();
MavenId id = MavenArtifactCoordinatesHelper.getId(context);
MavenDomShortArtifactCoordinates coordinates = MavenArtifactCoordinatesHelper.getCoordinates(context);
return selectStrategy(context).getVariants(id, manager, coordinates);
return selectStrategy(context).getVariants(id, searchService, coordinates);
}
protected abstract Set<String> doGetVariants(MavenId id, MavenProjectIndicesManager manager);
protected abstract Set<String> doGetVariants(MavenId id, DependencySearchService searchService);
@Override
public PsiElement resolve(String o, ConvertContext context) {
......@@ -94,7 +98,14 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert
@Override
public LocalQuickFix[] getQuickFixes(ConvertContext context) {
return ArrayUtil.append(super.getQuickFixes(context), new MyUpdateIndicesFix());
MavenId id = MavenArtifactCoordinatesHelper.getId(context);
MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(context.getProject());
if (manager.hasOfflineIndexes()) {
return ArrayUtil.append(super.getQuickFixes(context), new MyUpdateIndicesFix());
}
else {
return super.getQuickFixes(context);
}
}
@Override
......@@ -191,8 +202,8 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert
return doIsValid(id, manager, context) || resolveBySpecifiedPath() != null;
}
public Set<String> getVariants(MavenId id, MavenProjectIndicesManager manager, MavenDomShortArtifactCoordinates coordinates) {
return doGetVariants(id, manager);
public Set<String> getVariants(MavenId id, DependencySearchService searchService, MavenDomShortArtifactCoordinates coordinates) {
return doGetVariants(id, searchService);
}
public PsiFile resolve(MavenId id, ConvertContext context) {
......@@ -318,21 +329,6 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert
public PsiFile resolveBySpecifiedPath() {
return myDependency.getSystemPath().getValue();
}
@Override
public Set<String> getVariants(MavenId id, MavenProjectIndicesManager manager, MavenDomShortArtifactCoordinates coordinates) {
if (StringUtil.isEmpty(id.getGroupId())) {
Set<String> result = new THashSet<>();
for (String each : manager.getGroupIds()) {
id = new MavenId(each, id.getArtifactId(), id.getVersion());
result.addAll(super.getVariants(id, manager, coordinates));
}
return result;
}
return super.getVariants(id, manager, coordinates);
}
}
private class ExclusionStrategy extends ConverterStrategy {
......@@ -372,25 +368,17 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert
}
@Override
public Set<String> getVariants(MavenId id, MavenProjectIndicesManager manager, MavenDomShortArtifactCoordinates coordinates) {
public Set<String> getVariants(MavenId id, DependencySearchService searchService, MavenDomShortArtifactCoordinates coordinates) {
if (StringUtil.isEmpty(id.getGroupId())) {
Set<String> result = new THashSet<>();
for (String each : getGroupIdVariants(manager, coordinates)) {
for (String each : MavenArtifactUtil.DEFAULT_GROUPS) {
id = new MavenId(each, id.getArtifactId(), id.getVersion());
result.addAll(super.getVariants(id, manager, coordinates));
result.addAll(super.getVariants(id, searchService, coordinates));
}
return result;
}
return super.getVariants(id, manager, coordinates);
}
private String[] getGroupIdVariants(MavenProjectIndicesManager manager, MavenDomShortArtifactCoordinates coordinates) {
if (DomUtil.hasXml(coordinates.getGroupId())) {
Set<String> strings = manager.getGroupIds();
return ArrayUtil.toStringArray(strings);
}
return MavenArtifactUtil.DEFAULT_GROUPS;
return super.getVariants(id, searchService, coordinates);
}
@Override
......
......@@ -22,10 +22,12 @@ import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.project.MavenProject;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoordinatesConverter implements MavenSmartConverter<String> {
@Override
......@@ -34,7 +36,7 @@ public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoord
if (manager.hasGroupId(id.getGroupId())) return true;
// Check if artifact was found on importing.
// Check if artifact was found on importing.
MavenProject mavenProject = findMavenProject(context);
if (mavenProject != null) {
for (MavenArtifact artifact : mavenProject.findDependencies(id.getGroupId(), id.getArtifactId())) {
......@@ -48,8 +50,8 @@ public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoord
}
@Override
protected Set<String> doGetVariants(MavenId id, MavenProjectIndicesManager manager) {
return manager.getGroupIds();
protected Set<String> doGetVariants(MavenId id, DependencySearchService searchService) {
return searchService.findGroupCandidates(id).stream().map(s -> s.getGroupId()).collect(Collectors.toSet());
}
@Nullable
......@@ -88,7 +90,7 @@ public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoord
context.commitDocument();
PsiFile contextFile = context.getFile();
if(!(contextFile instanceof XmlFile)) return;
if (!(contextFile instanceof XmlFile)) return;
XmlFile xmlFile = (XmlFile)contextFile;
......@@ -109,5 +111,4 @@ public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoord
MavenDependencyCompletionUtil.addTypeAndClassifierAndVersion(context, dependency, item.getLookupString(), artifactId);
}
}
}
......@@ -36,8 +36,8 @@ public class MavenArtifactCoordinatesHelper {
if (coords instanceof MavenDomArtifactCoordinates) {
version = ((MavenDomArtifactCoordinates)coords).getVersion().getStringValue();
}
return new MavenId(coords.getGroupId().getStringValue(),
coords.getArtifactId().getStringValue(),
version);
return new MavenId(MavenDependencyCompletionUtil.removeDummy(coords.getGroupId().getStringValue()),
MavenDependencyCompletionUtil.removeDummy(coords.getArtifactId().getStringValue()),
MavenDependencyCompletionUtil.removeDummy(version));
}
}
......@@ -19,6 +19,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.xml.ConvertContext;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import java.util.Collections;
import java.util.Set;
......@@ -40,7 +41,7 @@ public class MavenArtifactCoordinatesVersionConverter extends MavenArtifactCoord
}
@Override
protected Set<String> doGetVariants(MavenId id, MavenProjectIndicesManager manager) {
protected Set<String> doGetVariants(MavenId id, DependencySearchService searchService) {
// Do nothing. Completion variants are generated by MavenVersionCompletionContributor.
return Collections.emptySet();
}
......
......@@ -18,19 +18,28 @@ package org.jetbrains.idea.maven.dom.converters;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils;
import org.jetbrains.idea.maven.dom.model.*;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import java.util.Set;
import javax.swing.*;
import java.util.List;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER_TRIMMED;
/**
* @author Sergey Evdokimov
......@@ -89,11 +98,11 @@ public class MavenDependencyCompletionUtil {
}
}
MavenProjectIndicesManager manager = MavenProjectIndicesManager.getInstance(project);
DependencySearchService service = MavenProjectIndicesManager.getInstance(project).getSearchService();
Set<String> versions = manager.getVersions(groupId, artifactId);
List<MavenDependencyCompletionItem> versions = service.findAllVersions(new MavenDependencyCompletionItem(groupId, artifactId, null));
if (versions.size() == 1) {
dependency.getVersion().setStringValue(ContainerUtil.getFirstItem(versions));
dependency.getVersion().setStringValue(ContainerUtil.getFirstItem(versions).getVersion());
return;
}
......@@ -113,4 +122,57 @@ public class MavenDependencyCompletionUtil {
() -> new CodeCompletionHandlerBase(completionType).invokeCompletion(context.getProject(), context.getEditor()));
}
public static LookupElementBuilder lookupElement(MavenDependencyCompletionItem item, String lookup) {
return LookupElementBuilder.create(item, lookup)
.withIcon(getIcon(item.getType()));
}
public static LookupElementBuilder lookupElement(MavenDependencyCompletionItem item) {
return lookupElement(item, getLookupString(item));
}
@Nullable
public static Icon getIcon(@Nullable MavenDependencyCompletionItem.Type type) {
if (type == null) {
return null;
}
switch (type) {
case REMOTE:
return AllIcons.Nodes.PpWeb;
case LOCAL:
return AllIcons.Nodes.PpLibFolder;
case CACHED_ERROR:
return AllIcons.Nodes.PpInvalid;
}
return null;
}
public static String getLookupString(MavenDependencyCompletionItem description) {
StringBuilder builder = new StringBuilder(description.getGroupId());
if (description.getArtifactId() == null) {
builder.append(":...");
}
else {
builder.append(":").append(description.getArtifactId());
if (description.getPackaging() != null) {
builder.append(":").append(description.getPackaging());
}
if (description.getVersion() != null) {
builder.append(":").append(description.getVersion());
}
else {
builder.append(":...");
}
}
return builder.toString();
}
public static @NotNull String removeDummy(@Nullable String str) {
if(str ==null){
return "";
}
return StringUtil.trim(str.replace(DUMMY_IDENTIFIER, "").replace(DUMMY_IDENTIFIER_TRIMMED, ""));
}
}
......@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.dom.model;
import com.intellij.ide.presentation.Presentation;
import com.intellij.spellchecker.xml.NoSpellchecking;
import com.intellij.util.xml.Convert;
import com.intellij.util.xml.DomElement;
......@@ -22,7 +23,10 @@ import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.Required;
import org.jetbrains.idea.maven.dom.converters.MavenArtifactCoordinatesArtifactIdConverter;
import org.jetbrains.idea.maven.dom.converters.MavenArtifactCoordinatesGroupIdConverter;
import org.jetbrains.idea.maven.dom.model.presentation.MavenArtifactCoordinatesPresentationProvider;
@Presentation(typeName = "Dependency", icon = "AllIcons.Nodes.PpLib", provider = MavenArtifactCoordinatesPresentationProvider.class)
public interface MavenDomShortArtifactCoordinates extends DomElement {
@Required
@NoSpellchecking
......
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.dom.model.completion;
import com.intellij.codeInsight.completion.CompletionContributor;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
import com.intellij.psi.xml.XmlTokenType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil;
import org.jetbrains.idea.maven.dom.model.completion.insert.MavenDependencyInsertHandler;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.utils.MavenLog;
import java.util.List;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER_TRIMMED;
public class MavenArtifactCompletionContributor extends CompletionContributor {
@Override
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
if (System.currentTimeMillis() > 1) return;
try {
PsiElement xmlText = parameters.getPosition().getParent();
if (!(xmlText instanceof XmlText)) return;
PsiElement tag = xmlText.getParent();
if (!(tag instanceof XmlTag)) return;
XmlTag parentTag = (XmlTag)tag;
XmlText currentText = (XmlText)xmlText;
if (!PsiImplUtil.isLeafElementOfType(xmlText.getPrevSibling(), XmlTokenType.XML_TAG_END)
|| !PsiImplUtil.isLeafElementOfType(xmlText.getNextSibling(), XmlTokenType.XML_END_TAG_START)) {
return;
}
if ("dependency".equals(parentTag.getName())) {
fillAllVariants(parameters, result, currentText, parentTag, MavenProjectIndicesManager.getInstance(tag.getProject()));
}
}
catch (Exception e) {
MavenLog.LOG.error(e);
}
}
private static String getCoordValue(XmlTag dependencyTag, final String tagName) {
String result = null;
for (XmlTag sub : dependencyTag.getSubTags()) {
if (tagName.equals(sub.getName())) {
XmlText type = PsiTreeUtil.getChildOfType(sub, XmlText.class);
if (type == null) {
break;
}
else {
result = type.getValue();
}
}
}
return result;
}
private void addToResultSet(CompletionResultSet result, XmlTag dependencyTag, List<MavenDependencyCompletionItem> candidates) {
for (MavenDependencyCompletionItem description : candidates) {
if (description.getGroupId() == null) {
continue;
}
result.addElement(MavenDependencyCompletionUtil.lookupElement(description)
.withInsertHandler(MavenDependencyInsertHandler.INSTANCE));
}
}
private void fillAllVariants(CompletionParameters parameters,
CompletionResultSet result,
XmlText xmlText,
XmlTag dependencyTag, MavenProjectIndicesManager instance) {
List<MavenDependencyCompletionItem> candidates = instance.getSearchService().findByTemplate(
getText(xmlText));
addToResultSet(result, dependencyTag, candidates);
}
@NotNull
private static String getText(XmlText text) {
return text.getValue().replace(DUMMY_IDENTIFIER, "").replace(DUMMY_IDENTIFIER_TRIMMED, "");
}
}
......@@ -4,8 +4,6 @@ package org.jetbrains.idea.maven.dom.model.completion;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
......@@ -23,6 +21,14 @@ import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.onlinecompletion.MavenScopeTable;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import java.util.List;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER;
import static com.intellij.codeInsight.completion.CompletionUtil.DUMMY_IDENTIFIER_TRIMMED;
import static com.intellij.patterns.StandardPatterns.string;
/**
* @author Sergey Evdokimov
......@@ -43,7 +49,7 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
if (!"dependency".equals(dependencyTag.getName())) return;
if (!PsiImplUtil.isLeafElementOfType(xmlText.getPrevSibling(), XmlTokenType.XML_TAG_END)
|| !PsiImplUtil.isLeafElementOfType(xmlText.getNextSibling(), XmlTokenType.XML_END_TAG_START)) {
|| !PsiImplUtil.isLeafElementOfType(xmlText.getNextSibling(), XmlTokenType.XML_END_TAG_START)) {
return;
}
......@@ -54,16 +60,14 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
return;
}
MavenProjectIndicesManager indicesManager = MavenProjectIndicesManager.getInstance(project);
for (String groupId : indicesManager.getGroupIds()) {
for (String artifactId : indicesManager.getArtifactIds(groupId)) {
LookupElement builder = LookupElementBuilder.create(groupId + ':' + artifactId)
.withIcon(AllIcons.Nodes.PpLib).withInsertHandler(MavenDependencyInsertHandler.INSTANCE);
List<MavenDependencyCompletionItem> candidates = MavenProjectIndicesManager.getInstance(project).getSearchService().findByTemplate(
StringUtil.trim(xmlText.getText().replace(DUMMY_IDENTIFIER, "").replace(DUMMY_IDENTIFIER_TRIMMED, "")));
result.addElement(builder);
}
for (MavenDependencyCompletionItem candidate : candidates) {
result.addElement(MavenDependencyCompletionUtil.lookupElement(candidate).withInsertHandler(MavenDependencyInsertHandler.INSTANCE));
}
result.restartCompletionOnPrefixChange(string().containsChars(":-."));
}
private static class MavenDependencyInsertHandler implements InsertHandler<LookupElement> {
......@@ -72,38 +76,50 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
@Override
public void handleInsert(@NotNull final InsertionContext context, @NotNull LookupElement item) {
String s = item.getLookupString();
int idx = s.indexOf(':');
Object obj = item.getObject();
if (!(obj instanceof MavenDependencyCompletionItem)) {
return;
}
String groupId = s.substring(0, idx);
String artifactId = s.substring(idx + 1);
MavenDependencyCompletionItem dependencyToSet = (MavenDependencyCompletionItem)obj;
int startOffset = context.getStartOffset();
PsiFile psiFile = context.getFile();
DomFileElement<MavenDomProjectModel> domModel = DomManager.getDomManager(context.getProject()).getFileElement((XmlFile)psiFile, MavenDomProjectModel.class);
DomFileElement<MavenDomProjectModel> domModel =
DomManager.getDomManager(context.getProject()).getFileElement((XmlFile)psiFile, MavenDomProjectModel.class);
if (domModel == null) return;
boolean shouldInvokeCompletion = false;
MavenDomDependency managedDependency = MavenDependencyCompletionUtil.findManagedDependency(domModel.getRootElement(),
context.getProject(), groupId, artifactId);
MavenDomDependency managedDependency = findManagedDomDependency(context, dependencyToSet, domModel);
if (managedDependency == null) {
String value = "<groupId>" + groupId + "</groupId>\n" +
"<artifactId>" + artifactId + "</artifactId>\n" +
"<version></version>";
String classifier =
dependencyToSet.getClassifier() == null ? "" : "<classifier>" + dependencyToSet.getClassifier() + "</classifier>\n";
String packaging =
dependencyToSet.getPackaging() == null || dependencyToSet.getPackaging().equals("jar")
? ""
: "<packaging>" + dependencyToSet.getPackaging() + "</packaging>\n";
String usualScope = MavenScopeTable.getUsualScope(dependencyToSet);
String scope = usualScope == null ? "" : "<scope>" + usualScope + "</scope>\n";
String version = dependencyToSet.getVersion() == null ? "" : dependencyToSet.getVersion();
String value = "<groupId>" + dependencyToSet.getGroupId() + "</groupId>\n" +
"<artifactId>" + dependencyToSet.getArtifactId() + "</artifactId>\n" +
classifier + packaging + scope +
"<version>" + version + "</version>";
context.getDocument().replaceString(startOffset, context.getSelectionEndOffset(), value);
context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - 10);
shouldInvokeCompletion = true;
if (dependencyToSet.getVersion() == null) {
context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - "</version>".length());
shouldInvokeCompletion = true;
}
}
else {
StringBuilder sb = new StringBuilder();
sb.append("<groupId>").append(groupId).append("</groupId>\n")
.append("<artifactId>").append(artifactId).append("</artifactId>\n");
sb.append("<groupId>").append(dependencyToSet.getGroupId()).append("</groupId>\n")
.append("<artifactId>").append(dependencyToSet.getArtifactId()).append("</artifactId>\n");
String type = managedDependency.getType().getRawText();
if (type != null && !type.equals("jar")) {
......@@ -133,5 +149,17 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
MavenDependencyCompletionUtil.invokeCompletion(context, CompletionType.BASIC);
}
}
private MavenDomDependency findManagedDomDependency(@NotNull InsertionContext context,
MavenDependencyCompletionItem dependencyToSet,
DomFileElement<MavenDomProjectModel> domModel) {
if (dependencyToSet.getGroupId() == null || dependencyToSet.getArtifactId() == null) {
return null;
}
return MavenDependencyCompletionUtil.findManagedDependency(domModel.getRootElement(),
context.getProject(),
dependencyToSet.getGroupId(),
dependencyToSet.getArtifactId());
}
}
}
......@@ -15,7 +15,6 @@
*/
package org.jetbrains.idea.maven.dom.model.completion;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.completion.impl.NegatingComparable;
import com.intellij.codeInsight.lookup.LookupElement;
......@@ -33,13 +32,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.MavenVersionComparable;
import org.jetbrains.idea.maven.dom.converters.MavenArtifactCoordinatesVersionConverter;
import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomArtifactCoordinates;
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.server.MavenServerManager;
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryDescription;
import java.util.Set;
import java.util.List;
/**
* @author Sergey Evdokimov
......@@ -61,6 +61,10 @@ public class MavenVersionCompletionContributor extends CompletionContributor {
XmlTag tag = (XmlTag)tagElement;
if (!"version".equals(tag.getName())) {
return;
}
Project project = element.getProject();
DomElement domElement = DomManager.getDomManager(project).getDomElement(tag);
......@@ -78,6 +82,7 @@ public class MavenVersionCompletionContributor extends CompletionContributor {
if (StringUtil.isEmptyOrSpaces(artifactId)) return;
CompletionResultSet newResultSet = result.withRelevanceSorter(CompletionService.getCompletionService().emptySorter().weigh(
new LookupElementWeigher("mavenVersionWeigher") {
@Nullable
......@@ -87,28 +92,23 @@ public class MavenVersionCompletionContributor extends CompletionContributor {
}
}));
MavenProjectIndicesManager indicesManager = MavenProjectIndicesManager.getInstance(project);
Set<String> versions;
List<MavenDependencyCompletionItem> completionItems = searchVersions(groupId, artifactId, coordinates, project);
if (StringUtil.isEmptyOrSpaces(groupId)) {
if (!(coordinates instanceof MavenDomPlugin)) return;
versions = indicesManager.getVersions(MavenArtifactUtil.DEFAULT_GROUPS[0], artifactId);
for (int i = 0; i < MavenArtifactUtil.DEFAULT_GROUPS.length; i++) {
versions = Sets.union(versions, indicesManager.getVersions(MavenArtifactUtil.DEFAULT_GROUPS[i], artifactId));
}
}
else {
versions = indicesManager.getVersions(groupId, artifactId);
for (MavenDependencyCompletionItem item : completionItems) {
newResultSet.addElement(MavenDependencyCompletionUtil.lookupElement(item, item.getVersion()));
}
for (String version : versions) {
newResultSet.addElement(LookupElementBuilder.create(version));
if (MavenServerManager.getInstance().isUseMaven2()) {
newResultSet.addElement(LookupElementBuilder.create(RepositoryLibraryDescription.ReleaseVersionId).withStrikeoutness(true));
newResultSet.addElement(LookupElementBuilder.create(RepositoryLibraryDescription.LatestVersionId).withStrikeoutness(true));
}
newResultSet.addElement(LookupElementBuilder.create(RepositoryLibraryDescription.ReleaseVersionId));
newResultSet.addElement(LookupElementBuilder.create(RepositoryLibraryDescription.LatestVersionId));
}
}
private List<MavenDependencyCompletionItem> searchVersions(String groupId,
String artifactId,
MavenDomArtifactCoordinates coordinates,
Project project) {
return MavenProjectIndicesManager.getInstance(project).getSearchService()
.findAllVersions(new MavenDependencyCompletionItem(groupId, artifactId, null, null));
}
}
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.dom.model.completion.insert;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil;
import org.jetbrains.idea.maven.onlinecompletion.MavenScopeTable;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.utils.MavenLog;
public class MavenDependencyInsertHandler implements InsertHandler<LookupElement> {
public static final InsertHandler<LookupElement> INSTANCE = new MavenDependencyInsertHandler();
@Override
public void handleInsert(@NotNull final InsertionContext context, @NotNull LookupElement item) {
try {
doHandleInsert(context, item);
}
catch (Throwable e) {
MavenLog.LOG.error(e);
}
}
private void doHandleInsert(@NotNull final InsertionContext context, @NotNull LookupElement item) {
MavenDependencyCompletionItem mavenId = extract(item);
int startOffset = context.getStartOffset();
PsiFile psiFile = context.getFile();
XmlTagImpl dependencyTag = getDependencyTag(startOffset, psiFile);
if (dependencyTag == null) {
return;
}
boolean shouldInvokeCompletion = setDependency(context, mavenId, dependencyTag);
context.commitDocument();
PsiElement e = getDependencyTag(startOffset, psiFile);
if (e != null) {
new ReformatCodeProcessor(psiFile.getProject(), psiFile, e.getTextRange(), false).run();
}
if (shouldInvokeCompletion) {
MavenDependencyCompletionUtil.invokeCompletion(context, CompletionType.BASIC);
}
}
@Nullable
private XmlTagImpl getDependencyTag(int startOffset, PsiFile psiFile) {
PsiElement e = psiFile.findElementAt(startOffset);
while (e != null && (!(e instanceof XmlTagImpl) || !"dependency".equals(((XmlTagImpl)e).getName()))) {
e = e.getParent();
}
return (XmlTagImpl)e;
}
private boolean setDependency(@NotNull InsertionContext context,
@NotNull MavenDependencyCompletionItem item, XmlTagImpl dependencyTag) {
int startOffset = dependencyTag.getStartOffset() + "<dependency>".length();
int endOffset = dependencyTag.getTextRange().getEndOffset();
while ("\n".equals(context.getDocument().getText(new TextRange(endOffset - 1, endOffset)))) {
endOffset--;
}
endOffset -= "</dependency>".length();
if (item.getGroupId() == null) {
return false;
}
else if (item.getArtifactId() == null) {
String value = "\n<groupId>" + item.getGroupId() + "</groupId>\n" +
"<artifactId></artifactId>";
context.getDocument().replaceString(startOffset, endOffset, value);
context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - "</artifactId>".length());
return true;
}
else if (item.getVersion() == null) {
String value = "\n<groupId>" + item.getGroupId() + "</groupId>\n" +
"<artifactId>" + item.getArtifactId() + "</artifactId>\n" +
"<version></version>\n";
context.getDocument().replaceString(startOffset, endOffset, value);
context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - "</version>".length());
return true;
}
else {
String classifier = item.getClassifier() == null ? "" : "<classifier>" + item.getClassifier() + "</classifier>\n";
String packaging =
item.getPackaging() == null || item.getPackaging().equals("jar") ? "" : "<packaging>" + item.getPackaging() + "</packaging>\n";
String usualScope = MavenScopeTable.getUsualScope(item);
String scope = usualScope == null ? "" : "<scope>" + usualScope + "</scope>\n";
String value = "\n<groupId>" + item.getGroupId() + "</groupId>\n" +
"<artifactId>" + item.getArtifactId() + "</artifactId>\n" +
classifier + packaging + scope +
"<version>" + item.getVersion() + "</version>\n";
context.getDocument().replaceString(startOffset, endOffset, value);
return false;
}
}
private static MavenDependencyCompletionItem extract(LookupElement item) {
Object object = item.getObject();
if (object instanceof MavenDependencyCompletionItem) {
return (MavenDependencyCompletionItem)object;
}
else {
return new MavenDependencyCompletionItem(item.getLookupString(), null);
}
}
}
/*
* 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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.openapi.application.ApplicationManager;
......
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.icons.AllIcons;
......@@ -14,8 +14,9 @@ import com.intellij.util.Alarm;
import com.intellij.util.ui.AbstractLayoutManager;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.model.MavenArtifactInfo;
import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.utils.MavenLog;
import javax.swing.*;
......@@ -180,7 +181,7 @@ public class MavenArtifactSearchPanel extends JPanel {
for (MavenArtifactSearchResult searchResult : result) {
if (searchResult.versions.isEmpty()) continue;
MavenArtifactInfo artifactInfo = searchResult.versions.get(0);
MavenDependencyCompletionItem artifactInfo = searchResult.getSearchResults().get(0);
final String managedVersion = myManagedDependenciesMap.get(Pair.create(artifactInfo.getGroupId(), artifactInfo.getArtifactId()));
if (managedVersion != null) {
Collections.sort(searchResult.versions, (o1, o2) -> {
......@@ -219,12 +220,12 @@ public class MavenArtifactSearchPanel extends JPanel {
for (TreePath each : myResultList.getSelectionPaths()) {
Object sel = each.getLastPathComponent();
MavenArtifactInfo info;
if (sel instanceof MavenArtifactInfo) {
info = (MavenArtifactInfo)sel;
MavenDependencyCompletionItem info;
if (sel instanceof MavenDependencyCompletionItem) {
info = (MavenDependencyCompletionItem)sel;
}
else {
info = ((MavenArtifactSearchResult)sel).versions.get(0);
info = ((MavenArtifactSearchResult)sel).getSearchResults().get(0);
}
result.add(new MavenId(info.getGroupId(), info.getArtifactId(), info.getVersion()));
}
......@@ -357,17 +358,20 @@ public class MavenArtifactSearchPanel extends JPanel {
else if (value instanceof MavenArtifactSearchResult) {
formatSearchResult(tree, (MavenArtifactSearchResult)value, selected);
}
else if (value instanceof MavenArtifactInfo) {
MavenArtifactInfo info = (MavenArtifactInfo)value;
else if (value instanceof MavenDependencyCompletionItem) {
MavenDependencyCompletionItem info = (MavenDependencyCompletionItem)value;
String version = info.getVersion();
Icon icon = MavenDependencyCompletionUtil.getIcon(info.getType());
String managedVersion = myManagedDependenciesMap.get(Pair.create(info.getGroupId(), info.getArtifactId()));
if (managedVersion != null && managedVersion.equals(version)) {
myLeftComponent.setIcon(icon);
myLeftComponent.append(version, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
myLeftComponent.append(" (from <dependencyManagement>)", SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
else {
myLeftComponent.setIcon(icon);
myLeftComponent.append(version, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
......@@ -376,12 +380,12 @@ public class MavenArtifactSearchPanel extends JPanel {
}
protected void formatSearchResult(JTree tree, MavenArtifactSearchResult searchResult, boolean selected) {
MavenArtifactInfo info = searchResult.versions.get(0);
MavenDependencyCompletionItem info = searchResult.getSearchResults().get(0);
myLeftComponent.setIcon(AllIcons.Nodes.PpLib);
appendArtifactInfo(myLeftComponent, info, selected);
}
protected void appendArtifactInfo(SimpleColoredComponent component, MavenArtifactInfo info, boolean selected) {
protected void appendArtifactInfo(SimpleColoredComponent component, MavenDependencyCompletionItem info, boolean selected) {
component.append(info.getGroupId() + ":", getGrayAttributes(selected));
component.append(info.getArtifactId(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
component.append(":" + info.getVersion(), getGrayAttributes(selected));
......@@ -401,11 +405,11 @@ public class MavenArtifactSearchPanel extends JPanel {
@Override
protected void formatSearchResult(JTree tree, MavenArtifactSearchResult searchResult, boolean selected) {
MavenClassSearchResult classResult = (MavenClassSearchResult)searchResult;
MavenArtifactInfo info = searchResult.versions.get(0);
MavenDependencyCompletionItem info = searchResult.getSearchResults().get(0);
myLeftComponent.setIcon(AllIcons.Nodes.Class);
myLeftComponent.append(classResult.className, SimpleTextAttributes.REGULAR_ATTRIBUTES);
myLeftComponent.append(" (" + classResult.packageName + ")", getGrayAttributes(selected));
myLeftComponent.append(classResult.getClassName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
myLeftComponent.append(" (" + classResult.getPackageName() + ")", getGrayAttributes(selected));
appendArtifactInfo(myRightComponent, info, selected);
}
......
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.model.MavenArtifactInfo;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MavenArtifactSearchResult {
public List<MavenArtifactInfo> versions = new ArrayList<>();
@Deprecated
/* @deprecated use getSearchResults instead */
public List<MavenArtifactInfo> versions;
private List<MavenDependencyCompletionItem> myResults;
@Deprecated
public MavenArtifactSearchResult() {
this(new ArrayList<>());
}
public MavenArtifactSearchResult(@NotNull List<MavenDependencyCompletionItem> results) {
setVersions(results);
this.myResults = results;
}
public void setResults(List<MavenDependencyCompletionItem> results) {
setVersions(results);
myResults = results;
}
private void setVersions(@NotNull List<MavenDependencyCompletionItem> results) {
versions = ContainerUtil.map(results, d -> new MavenArtifactInfo(d, d.getPackaging(), d.getClassifier()));
}
public List<MavenDependencyCompletionItem> getSearchResults(){
return Collections.unmodifiableList(myResults);
}
}
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.idea.maven.model.MavenArtifactInfo;
import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.*;
import static com.intellij.openapi.util.text.StringUtil.*;
import static org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters.Flags.ALL_VERSIONS;
import static org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters.Flags.FULL_RESOLVE;
public class MavenArtifactSearcher extends MavenSearcher<MavenArtifactSearchResult> {
private static final Pattern VERSION_PATTERN = Pattern.compile("[.\\d]+");
@Override
protected List<MavenArtifactSearchResult> searchImpl(Project project, String pattern, int maxResult) {
List<String> parts = new ArrayList<>();
for (String each : tokenize(pattern, " :")) {
parts.add(trimStart(trimEnd(each, "*"), "*"));
if (StringUtil.isEmpty(pattern)) {
return Collections.emptyList();
}
DependencySearchService service = MavenProjectIndicesManager.getInstance(project).getSearchService();
List<MavenDependencyCompletionItem> searchResults =
service.findByTemplate(pattern, new SearchParameters(1000, 5000, EnumSet.of(FULL_RESOLVE, ALL_VERSIONS)));
return processResults(searchResults, pattern);
}
List<MavenArtifactSearchResult> searchResults = ContainerUtil.newSmartList();
MavenProjectIndicesManager m = MavenProjectIndicesManager.getInstance(project);
int count = 0;
List<MavenArtifactInfo> versions = new ArrayList<>();
for (String groupId : m.getGroupIds()) {
if (count >= maxResult) break;
if (parts.size() < 1 || contains(groupId, parts.get(0))) {
for (String artifactId : m.getArtifactIds(groupId)) {
if (parts.size() < 2 || contains(artifactId, parts.get(1))) {
for (String version : m.getVersions(groupId, artifactId)) {
if (parts.size() < 3 || contains(version, parts.get(2))) {
versions.add(new MavenArtifactInfo(groupId, artifactId, version, "jar", null));
if (++count >= maxResult) break;
}
}
}
else if (parts.size() == 2 && VERSION_PATTERN.matcher(parts.get(1)).matches()) {
for (String version : m.getVersions(groupId, artifactId)) {
if (contains(version, parts.get(1))) {
versions.add(new MavenArtifactInfo(groupId, artifactId, version, "jar", null));
if (++count >= maxResult) break;
}
}
}
if (!versions.isEmpty()) {
MavenArtifactSearchResult searchResult = new MavenArtifactSearchResult();
searchResult.versions.addAll(versions);
searchResults.add(searchResult);
versions.clear();
}
if (count >= maxResult) break;
}
private static List<MavenArtifactSearchResult> processResults(List<MavenDependencyCompletionItem> searchResults, String pattern) {
Map<String, List<MavenDependencyCompletionItem>> results = new HashMap<>();
for (MavenDependencyCompletionItem item : searchResults) {
if (item.getGroupId() == null || item.getArtifactId() == null || item.getVersion() == null) {
continue;
}
String key = item.getGroupId() + ":" + item.getArtifactId();
if(!key.contains(pattern)){
continue;
}
List<MavenDependencyCompletionItem> list = results.get(key);
if (list == null) {
list = new ArrayList<>();
results.put(key, list);
}
list.add(item);
}
return searchResults;
;
return ContainerUtil.map(results.values(), MavenArtifactSearchResult::new);
}
}
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import java.util.List;
public class MavenClassSearchResult extends MavenArtifactSearchResult {
@Deprecated
/* @deprecated use getClassName */
public String className;
@Deprecated
/* @deprecated use getPackageName */
public String packageName;
public MavenClassSearchResult(@NotNull List<MavenDependencyCompletionItem> results, String className, String packageName) {
super(results);
this.className = className;
this.packageName = packageName;
}
public String getClassName() {
return className;
}
public String getPackageName() {
return packageName;
}
}
\ No newline at end of file
/*
* 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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import gnu.trove.THashMap;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.WildcardQuery;
import org.jetbrains.idea.maven.model.MavenArtifactInfo;
import org.jetbrains.idea.maven.onlinecompletion.DependencySearchService;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItem;
import org.jetbrains.idea.maven.onlinecompletion.model.MavenDependencyCompletionItemWithClass;
import org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters;
import org.jetbrains.idea.maven.server.MavenServerIndexer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters.Flags.ALL_VERSIONS;
import static org.jetbrains.idea.maven.onlinecompletion.model.SearchParameters.Flags.FULL_RESOLVE;
public class MavenClassSearcher extends MavenSearcher<MavenClassSearchResult> {
public static final String TERM = MavenServerIndexer.SEARCH_TERM_CLASS_NAMES;
@Override
protected List<MavenClassSearchResult> searchImpl(Project project, String pattern, int maxResult) {
Pair<String, Query> patternAndQuery = preparePatternAndQuery(pattern);
MavenProjectIndicesManager m = MavenProjectIndicesManager.getInstance(project);
Set<MavenArtifactInfo> infos = m.search(patternAndQuery.second, maxResult);
return new ArrayList<>(processResults(infos, patternAndQuery.first, maxResult));
DependencySearchService service = MavenProjectIndicesManager.getInstance(project).getSearchService();
List<MavenDependencyCompletionItemWithClass> items = service.findClasses(pattern, new SearchParameters(1000, 5000, EnumSet
.of(FULL_RESOLVE, ALL_VERSIONS)));
return processResults(items, maxResult);
}
protected Pair<String, Query> preparePatternAndQuery(String pattern) {
protected String preparePattern(String pattern) {
pattern = pattern.toLowerCase();
if (pattern.trim().length() == 0) {
return new Pair<>(pattern, new MatchAllDocsQuery());
return pattern;
}
List<String> parts = StringUtil.split(pattern, ".");
......@@ -64,81 +45,52 @@ public class MavenClassSearcher extends MavenSearcher<MavenClassSearchResult> {
newPattern.append(className.trim());
if (!exactSearch) newPattern.append("*");
pattern = newPattern.toString();
String queryPattern = "*/" + pattern.replaceAll("\\.", "/");
return new Pair<>(pattern, new WildcardQuery(new Term(TERM, queryPattern)));
return newPattern.toString();
}
protected Collection<MavenClassSearchResult> processResults(Set<MavenArtifactInfo> infos, String pattern, int maxResult) {
if (pattern.length() == 0 || pattern.equals("*")) {
pattern = "^/(.*)$";
}
else {
pattern = pattern.replace(".", "/");
protected List<MavenClassSearchResult> processResults(List<MavenDependencyCompletionItemWithClass> searchResults,
int maxResult) {
int lastDot = pattern.lastIndexOf("/");
String packagePattern = lastDot == -1 ? "" : (pattern.substring(0, lastDot) + "/");
String classNamePattern = lastDot == -1 ? pattern : pattern.substring(lastDot + 1);
packagePattern = packagePattern.replaceAll("\\*", ".*?");
classNamePattern = classNamePattern.replaceAll("\\*", "[^/]*?");
pattern = packagePattern + classNamePattern;
pattern = ".*?/" + pattern;
pattern = "^(" + pattern + ")$";
}
Pattern p;
try {
p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
}
catch (PatternSyntaxException e) {
return Collections.emptyList();
}
Map<String, List<MavenDependencyCompletionItem>> classes = new HashMap<>();
Map<String, MavenClassSearchResult> result = new THashMap<>();
for (MavenArtifactInfo each : infos) {
if (each.getClassNames() == null) continue;
Matcher matcher = p.matcher(each.getClassNames());
while (matcher.find()) {
String classFQName = matcher.group(1);
classFQName = classFQName.replace("/", ".");
classFQName = StringUtil.trimStart(classFQName, ".");
String key = makeKey(classFQName, each);
MavenClassSearchResult classResult = result.get(key);
if (classResult == null) {
classResult = new MavenClassSearchResult();
int pos = classFQName.lastIndexOf(".");
if (pos == -1) {
classResult.packageName = "default package";
classResult.className = classFQName;
}
else {
classResult.packageName = classFQName.substring(0, pos);
classResult.className = classFQName.substring(pos + 1);
}
result.put(key, classResult);
for (MavenDependencyCompletionItemWithClass item : searchResults) {
for (String className : item.getNames()) {
List<MavenDependencyCompletionItem> list = classes.get(className);
if (list == null) {
list = new ArrayList<>();
classes.put(className, list);
}
classResult.versions.add(each);
if (result.size() > maxResult) break;
list.add(item);
}
}
return result.values();
List<MavenClassSearchResult> results = new ArrayList<>();
for (Map.Entry<String, List<MavenDependencyCompletionItem>> entry : classes.entrySet()) {
String className;
String packageName;
int pos = entry.getKey().lastIndexOf(".");
if (pos == -1) {
packageName = "default package";
className = entry.getKey();
}
else {
packageName = entry.getKey().substring(0, pos);
className = entry.getKey().substring(pos + 1);
}
MavenClassSearchResult classResult = new MavenClassSearchResult(entry.getValue(), className, packageName);
results.add(classResult);
}
return results;
}
@Override
protected String makeSortKey(MavenClassSearchResult result) {
return makeKey(result.className, result.versions.get(0));
return makeKey(result.getClassName(), result.getSearchResults().get(0));
}
private String makeKey(String className, MavenArtifactInfo info) {
private String makeKey(String className, MavenDependencyCompletionItem info) {
return className + " " + super.makeKey(info);
}
}
\ No newline at end of file
/*
* Copyright 2000-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.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.indices;
import com.intellij.jarRepository.services.bintray.BintrayModel;
......@@ -52,7 +38,8 @@ import static com.intellij.openapi.util.text.StringUtil.join;
import static com.intellij.openapi.util.text.StringUtil.split;
import static com.intellij.util.containers.ContainerUtil.notNullize;
public class MavenIndex {
@Deprecated
public class MavenIndex implements MavenSearchIndex {
private static final String CURRENT_VERSION = "5";
protected static final String INDEX_INFO_FILE = "index.properties";
......@@ -72,10 +59,6 @@ public class MavenIndex {
private static final String VERSIONS_MAP_FILE = "versions-map.dat";
private static final String ARCHETYPES_MAP_FILE = "archetypes-map.dat";
public enum Kind {
LOCAL, REMOTE
}
private final MavenIndexerWrapper myNexusIndexer;
private final NotNexusIndexer myNotNexusIndexer;
private final File myDir;
......@@ -170,6 +153,7 @@ public class MavenIndex {
return null;
}
@Override
public void registerId(String repositoryId) throws MavenIndexException {
if (myRegisteredRepositoryIds.add(repositoryId)) {
save();
......@@ -252,6 +236,7 @@ public class MavenIndex {
}
}
@Override
public synchronized void close(boolean releaseIndexContext) {
try {
if (myData != null) myData.close(releaseIndexContext);
......@@ -289,40 +274,49 @@ public class MavenIndex {
}
}
@Override
public String getRepositoryId() {
return myId.getValue();
}
@Override
public File getRepositoryFile() {
return myKind == Kind.LOCAL ? new File(myRepositoryPathOrUrl) : null;
}
@Override
public String getRepositoryUrl() {
return myKind == Kind.REMOTE ? myRepositoryPathOrUrl : null;
}
@Override
public String getRepositoryPathOrUrl() {
return myRepositoryPathOrUrl;
}
@Override
public Kind getKind() {
return myKind;
}
@Override
public boolean isFor(Kind kind, String pathOrUrl) {
if (myKind != kind) return false;
if (kind == Kind.LOCAL) return FileUtil.pathsEqual(myRepositoryPathOrUrl, normalizePathOrUrl(pathOrUrl));
return myRepositoryPathOrUrl.equalsIgnoreCase(normalizePathOrUrl(pathOrUrl));
}
@Override
public synchronized long getUpdateTimestamp() {
return myUpdateTimestamp == null ? -1 : myUpdateTimestamp;
}
@Override
public synchronized String getFailureMessage() {
return myFailureMessage;
}
@Override
public void updateOrRepair(boolean fullUpdate, MavenGeneralSettings settings, MavenProgressIndicator progress)
throws MavenProcessCanceledException {
try {
......@@ -401,7 +395,7 @@ public class MavenIndex {
synchronized (this) {
IndexData oldData = myData;
if(oldData != null) {
if (oldData != null) {
oldData.close(true);
}
}
......@@ -748,10 +742,6 @@ public class MavenIndex {
}
}
public interface IndexListener {
void indexIsBroken(@NotNull MavenIndex index);
}
private class MyIndexRepositoryIdsProvider implements CachedValueProvider<String> {
@Nullable
@Override
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment