Skip to content

Commit d72e109

Browse files
committed
feat: add CAUpdateManifestIntentionAction mechanism to add an updateManifest annotation
so it will add some general information to manifest from data retrieved from dependencies and create CAUpdateManifestIntentionAction subclass to add redhat ga as repository to pom.xml Signed-off-by: Zvi Grinberg <[email protected]>
1 parent 4973983 commit d72e109

File tree

10 files changed

+218
-25
lines changed

10 files changed

+218
-25
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
ideaVersion = 2021.1
2-
projectVersion=0.9.0-SNAPSHOT
2+
projectVersion=0.7.1-SNAPSHOT
33
jetBrainsToken=invalid
44
jetBrainsChannel=stable

src/main/java/org/jboss/tools/intellij/componentanalysis/CAAnnotator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,11 @@ public void apply(@NotNull PsiFile file, Map<Dependency, Result> annotationResul
159159
.newAnnotation(getHighlightSeverity(report), messageBuilder.toString())
160160
.tooltip(tooltipBuilder.toString())
161161
.range(e);
162+
CAUpdateManifestIntentionAction patchManifest = this.patchManifest(file, report);
162163
builder.withFix(new SAIntentionAction());
163164
builder.withFix(this.createQuickFix(e, source, report));
164-
builder.create();
165+
builder.withFix(patchManifest);
166+
builder.create();
165167
}
166168
);
167169
}
@@ -191,7 +193,7 @@ private static HighlightSeverity getHighlightSeverity(DependencyReport report) {
191193
abstract protected Map<Dependency, List<PsiElement>> getDependencies(PsiFile file);
192194

193195
abstract protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySource source, DependencyReport report);
194-
196+
abstract protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport report);
195197
abstract protected boolean isQuickFixApplicable(PsiElement element);
196198

197199
private Map<Dependency, Result> matchDependencies(Map<Dependency, List<PsiElement>> dependencies,

src/main/java/org/jboss/tools/intellij/componentanalysis/CAIntentionAction.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,9 @@ public boolean startInWriteAction() {
8787
}
8888

8989
protected abstract void updateVersion(@NotNull Project project, Editor editor, PsiFile file, String version);
90-
9190
protected abstract @Nullable FileModifier createCAIntentionActionInCopy(PsiElement element);
9291

93-
//TODO
92+
9493
private static @NotNull String getRecommendedVersion(DependencyReport dependency) {
9594
String version=null;
9695
if(thereAreNoIssues(dependency))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2023 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
12+
package org.jboss.tools.intellij.componentanalysis;
13+
14+
import com.intellij.codeInsight.intention.IntentionAction;
15+
import com.intellij.codeInspection.util.IntentionFamilyName;
16+
import com.intellij.codeInspection.util.IntentionName;
17+
import com.intellij.openapi.editor.Editor;
18+
import com.intellij.openapi.project.Project;
19+
import com.intellij.psi.PsiElement;
20+
import com.intellij.psi.PsiFile;
21+
import com.intellij.util.IncorrectOperationException;
22+
import com.redhat.exhort.api.DependencyReport;
23+
import org.jetbrains.annotations.NotNull;
24+
25+
public abstract class CAUpdateManifestIntentionAction implements IntentionAction {
26+
27+
protected @SafeFieldForPreview PsiElement element;
28+
protected @SafeFieldForPreview DependencyReport dependency;
29+
30+
31+
protected CAUpdateManifestIntentionAction(PsiElement element, DependencyReport dependency) {
32+
this.element = element;
33+
this.dependency = dependency;
34+
}
35+
36+
@Override
37+
public @IntentionName @NotNull String getText() {
38+
return this.getTextImpl();
39+
}
40+
41+
protected abstract String getTextImpl();
42+
43+
@Override
44+
public @NotNull @IntentionFamilyName String getFamilyName() {
45+
return "RHDA";
46+
}
47+
48+
@Override
49+
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
50+
this.updateManifest(project, editor, file, this.dependency);
51+
}
52+
53+
protected abstract void updateManifest(Project project, Editor editor, PsiFile file, DependencyReport dependency);
54+
55+
@Override
56+
public boolean startInWriteAction() {
57+
return true;
58+
}
59+
60+
61+
}

src/main/java/org/jboss/tools/intellij/componentanalysis/golang/GoCAAnnotator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919
import com.intellij.psi.PsiFile;
2020
import com.intellij.psi.util.PsiTreeUtil;
2121
import com.redhat.exhort.api.DependencyReport;
22-
import org.jboss.tools.intellij.componentanalysis.CAAnnotator;
23-
import org.jboss.tools.intellij.componentanalysis.CAIntentionAction;
24-
import org.jboss.tools.intellij.componentanalysis.Dependency;
25-
import org.jboss.tools.intellij.componentanalysis.VulnerabilitySource;
22+
import org.jboss.tools.intellij.componentanalysis.*;
2623

2724
import java.util.*;
2825

@@ -81,6 +78,11 @@ protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySour
8178
return new GoCAIntentionAction(element, source, report);
8279
}
8380

81+
@Override
82+
protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport report) {
83+
return null;
84+
}
85+
8486
@Override
8587
protected boolean isQuickFixApplicable(PsiElement element) {
8688
return element instanceof VgoModuleSpec && ((VgoModuleSpec) element).getModuleVersion() != null;

src/main/java/org/jboss/tools/intellij/componentanalysis/maven/MavenCAAnnotator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
import com.intellij.psi.xml.XmlTag;
1919
import com.intellij.psi.xml.XmlText;
2020
import com.redhat.exhort.api.DependencyReport;
21-
import org.jboss.tools.intellij.componentanalysis.CAAnnotator;
22-
import org.jboss.tools.intellij.componentanalysis.CAIntentionAction;
23-
import org.jboss.tools.intellij.componentanalysis.Dependency;
24-
import org.jboss.tools.intellij.componentanalysis.VulnerabilitySource;
21+
import org.jboss.tools.intellij.componentanalysis.*;
2522

2623
import java.util.*;
2724
import java.util.stream.Collectors;
@@ -117,6 +114,11 @@ protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySour
117114
return new MavenCAIntentionAction(element, source, report);
118115
}
119116

117+
@Override
118+
protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport dependency) {
119+
return new MavenCAUpdateManifestIntentionAction(element,dependency);
120+
}
121+
120122
@Override
121123
protected boolean isQuickFixApplicable(PsiElement element) {
122124
if (element instanceof XmlTag) {
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package org.jboss.tools.intellij.componentanalysis.maven;
2+
3+
import com.intellij.icons.AllIcons;
4+
import com.intellij.openapi.editor.Document;
5+
import com.intellij.openapi.editor.Editor;
6+
import com.intellij.openapi.project.Project;
7+
import com.intellij.psi.PsiDirectory;
8+
import com.intellij.psi.PsiDocumentManager;
9+
import com.intellij.psi.PsiElement;
10+
import com.intellij.psi.PsiFile;
11+
import com.intellij.psi.impl.source.xml.XmlTagImpl;
12+
import com.intellij.psi.xml.XmlDocument;
13+
import com.intellij.psi.xml.XmlTag;
14+
import com.intellij.psi.xml.XmlText;
15+
import com.intellij.xml.util.XmlUtil;
16+
import com.redhat.exhort.api.DependencyReport;
17+
import com.redhat.exhort.api.PackageRef;
18+
import org.jboss.tools.intellij.componentanalysis.CAUpdateManifestIntentionAction;
19+
import org.jetbrains.annotations.NotNull;
20+
21+
import javax.xml.bind.annotation.XmlElementWrapper;
22+
import javax.xml.bind.annotation.XmlValue;
23+
import java.util.Arrays;
24+
import java.util.Objects;
25+
import java.util.Optional;
26+
import java.util.concurrent.atomic.AtomicReference;
27+
28+
public final class MavenCAUpdateManifestIntentionAction extends CAUpdateManifestIntentionAction {
29+
@Override
30+
protected String getTextImpl() {
31+
return "Add Redhat GA Maven Repository to your pom.xml";
32+
}
33+
34+
MavenCAUpdateManifestIntentionAction(PsiElement element, DependencyReport report) {
35+
super(element, report);
36+
}
37+
38+
@Override
39+
protected void updateManifest(Project project, Editor editor, PsiFile file, DependencyReport dependency) {
40+
PsiElement rootProjectElement = getRootPomElement(file);
41+
XmlTag repositories = new XmlTagImpl();
42+
XmlTag rootProjectXml = (XmlTag)rootProjectElement;
43+
if(Arrays.stream(rootProjectElement.getChildren()).noneMatch(psi -> psi instanceof XmlTag && ((XmlTag)psi).getName().equals("repositories"))) {
44+
45+
repositories = rootProjectXml.createChildTag("repositories",rootProjectXml.getNamespace(),"",false);
46+
repositories.setName("repositories");
47+
48+
}
49+
else {
50+
Optional<PsiElement> repoWrapper = Arrays.stream(rootProjectElement.getChildren()).filter(psi -> psi instanceof XmlTag && ((XmlTag) psi).getName().equals("repositories")).findFirst();
51+
if(repoWrapper.isPresent()) {
52+
repositories = (XmlTag)repoWrapper.get();
53+
}
54+
}
55+
56+
XmlTag repository = repositories.createChildTag("repository", repositories.getNamespace(), "", false);
57+
repository.setName("repository");
58+
59+
XmlTag id = repository.createChildTag("id", repository.getNamespace(), "redhat-ga", false);
60+
XmlTag name = repository.createChildTag("name", repository.getNamespace(), "Redhat GA Maven Repository", false);
61+
XmlTag url = repository.createChildTag("url", repository.getNamespace(), getRepositoryUrl(dependency), false);
62+
id.setName("id");
63+
name.setName("name");
64+
url.setName("url");
65+
id.getValue().setText("redhat-ga");
66+
name.getValue().setText("Redhat GA Maven Repository");
67+
url.getValue().setText(getRepositoryUrl(dependency));
68+
repository.addSubTag(id,false);
69+
repository.addSubTag(name,false);
70+
repository.addSubTag(url,false);
71+
// only after subtags created and populated, add them as subtags, so outer tags will be populated with their values.
72+
repositories.addSubTag(repository,true);
73+
rootProjectXml.addSubTag(repositories,true);
74+
75+
}
76+
77+
@NotNull
78+
private static PsiElement getRootPomElement(PsiFile file) {
79+
PsiElement rootProjectElement = Arrays.stream(file.getChildren())
80+
.filter(element -> element instanceof XmlDocument)
81+
.flatMap(element -> Arrays.stream(element.getChildren()))
82+
.filter(element -> element instanceof XmlTag && "project".equals(((XmlTag) element).getName())).findFirst().get();
83+
return rootProjectElement;
84+
}
85+
86+
private static String getRepositoryUrl(DependencyReport dependency) {
87+
return getRepositoryUrlFromPurl(dependency);
88+
}
89+
90+
private static String getRepositoryUrlFromPurl(DependencyReport dependency) {
91+
AtomicReference<PackageRef> packageRef = new AtomicReference<>();
92+
if(Objects.nonNull(dependency.getRecommendation()))
93+
{
94+
packageRef.set(dependency.getRecommendation());
95+
}
96+
else {
97+
dependency.getIssues().stream().filter(issue -> Objects.nonNull(issue.getRemediation().getTrustedContent())).findFirst().ifPresent( value -> packageRef.set(value.getRemediation().getTrustedContent().getRef()));
98+
}
99+
return packageRef.get().purl().getQualifiers().get("repository_url");
100+
}
101+
102+
@Override
103+
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
104+
boolean manifestIsPomXml = file != null && "pom.xml".equals(file.getName());
105+
boolean repositoryInPom = false;
106+
PsiElement rootPomElement = getRootPomElement(file);
107+
Optional<PsiElement> repoWrapper = Arrays.stream(rootPomElement.getChildren()).filter(psi -> psi instanceof XmlTag && ((XmlTag) psi).getName().equals("repositories")).findFirst();
108+
if (repoWrapper.isPresent()) {
109+
XmlTag repositories = (XmlTag) repoWrapper.get();
110+
repositoryInPom = Arrays.stream(repositories.getChildren())
111+
.flatMap(element -> Arrays.stream(element.getChildren()))
112+
.filter(element -> element instanceof XmlTag && "id".equals(((XmlTag) element).getName()))
113+
.flatMap(tagValue -> Arrays.stream(((XmlTag) tagValue).getValue().getChildren()))
114+
.anyMatch(tag -> tag instanceof XmlText && (((XmlText) tag).getValue().trim().equals("redhat-ga")));
115+
116+
}
117+
118+
return manifestIsPomXml && !repositoryInPom;
119+
120+
}
121+
}

src/main/java/org/jboss/tools/intellij/componentanalysis/npm/NpmCAAnnotator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
import com.intellij.psi.PsiElement;
1616
import com.intellij.psi.PsiFile;
1717
import com.redhat.exhort.api.DependencyReport;
18-
import org.jboss.tools.intellij.componentanalysis.CAAnnotator;
19-
import org.jboss.tools.intellij.componentanalysis.CAIntentionAction;
20-
import org.jboss.tools.intellij.componentanalysis.Dependency;
21-
import org.jboss.tools.intellij.componentanalysis.VulnerabilitySource;
18+
import org.jboss.tools.intellij.componentanalysis.*;
2219

2320
import java.util.*;
2421
import java.util.stream.Collectors;
@@ -80,6 +77,11 @@ protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySour
8077
return new NpmCAIntentionAction(element, source, report);
8178
}
8279

80+
@Override
81+
protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport report) {
82+
return null;
83+
}
84+
8385
@Override
8486
protected boolean isQuickFixApplicable(PsiElement element) {
8587
return element instanceof JsonProperty && ((JsonProperty) element).getValue() instanceof JsonStringLiteral;

src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/ce/PipCAAnnotator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import com.intellij.psi.PsiElement;
1515
import com.intellij.psi.PsiFile;
1616
import com.redhat.exhort.api.DependencyReport;
17-
import org.jboss.tools.intellij.componentanalysis.CAAnnotator;
18-
import org.jboss.tools.intellij.componentanalysis.CAIntentionAction;
19-
import org.jboss.tools.intellij.componentanalysis.Dependency;
20-
import org.jboss.tools.intellij.componentanalysis.VulnerabilitySource;
17+
import org.jboss.tools.intellij.componentanalysis.*;
2118
import org.jboss.tools.intellij.componentanalysis.pypi.PipCAInspection;
2219
import org.jboss.tools.intellij.componentanalysis.pypi.ce.requirements.psi.NameReq;
2320
import org.jboss.tools.intellij.componentanalysis.pypi.ce.requirements.psi.NameReqComment;
@@ -63,6 +60,11 @@ protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySour
6360
return new PipCAIntentionAction(element, source, report);
6461
}
6562

63+
@Override
64+
protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport report) {
65+
return null;
66+
}
67+
6668
@Override
6769
protected boolean isQuickFixApplicable(PsiElement element) {
6870
return element instanceof NameReq && ((NameReq) element).getVersionspec() != null;

src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/pro/PipCAAnnotator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
import com.intellij.psi.PsiFile;
1717
import com.intellij.psi.impl.source.tree.LeafPsiElement;
1818
import com.redhat.exhort.api.DependencyReport;
19-
import org.jboss.tools.intellij.componentanalysis.CAAnnotator;
20-
import org.jboss.tools.intellij.componentanalysis.CAIntentionAction;
21-
import org.jboss.tools.intellij.componentanalysis.Dependency;
22-
import org.jboss.tools.intellij.componentanalysis.VulnerabilitySource;
19+
import org.jboss.tools.intellij.componentanalysis.*;
2320
import org.jboss.tools.intellij.componentanalysis.pypi.PipCAInspection;
2421
import org.jetbrains.annotations.Nullable;
2522
import ru.meanmail.psi.NameReq;
@@ -84,6 +81,11 @@ protected CAIntentionAction createQuickFix(PsiElement element, VulnerabilitySour
8481
return new PipCAIntentionAction(element, source, report);
8582
}
8683

84+
@Override
85+
protected CAUpdateManifestIntentionAction patchManifest(PsiElement element, DependencyReport report) {
86+
return null;
87+
}
88+
8789
@Override
8890
protected boolean isQuickFixApplicable(PsiElement element) {
8991
return element instanceof NameReq && ((NameReq) element).getVersionspec() != null;

0 commit comments

Comments
 (0)