Check dependency versions for java diagnostics

This commit is contained in:
BoykoAlex
2022-05-04 13:13:28 -04:00
parent 0451dc4ba8
commit d78752e747
6 changed files with 126 additions and 30 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 2022 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,12 +21,14 @@ import org.slf4j.LoggerFactory;
public class SpringProjectUtil {
private static final String VERION_PATTERN_STR = "(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?";
public static final Logger log = LoggerFactory.getLogger(SpringProjectUtil.class);
private static final Pattern MAJOR_MINOR_VERSION = Pattern.compile("(0|[1-9]\\d*)\\.(0|[1-9]\\d*)");
// Pattern copied from https://semver.org/
private static final Pattern VERSION = Pattern.compile("(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?");
private static final Pattern VERSION = Pattern.compile(VERION_PATTERN_STR);
private static final Pattern SPRING_NAME = Pattern.compile("([a-z]+)(-[a-z]+)*");
@@ -107,4 +109,38 @@ public class SpringProjectUtil {
String name = cpe.getName();
return name.startsWith(libNamePrefix) && (!onlyLibs || name.endsWith(".jar"));
}
public static Version getDependencyVersion(IJavaProject jp, String dependency) {
try {
for (File f : IClasspathUtil.getBinaryRoots(jp.getClasspath(), (cpe) -> !cpe.isSystem())) {
String fileName = f.getName();
if (fileName.startsWith(dependency)) {
StringBuilder sb = new StringBuilder();
sb.append('^');
sb.append(dependency);
sb.append('-');
sb.append(VERION_PATTERN_STR);
sb.append(".jar$");
Pattern pattern = Pattern.compile(sb.toString());
Matcher matcher = pattern.matcher(fileName);
if (matcher.find() && matcher.groupCount() == 5) {
String major = matcher.group(1);
String minor = matcher.group(2);
String patch = matcher.group(3);
String qualifier = matcher.group(4);
return new Version(
Integer.parseInt(major),
Integer.parseInt(minor),
Integer.parseInt(patch),
qualifier
);
}
}
}
} catch (Exception e) {
log.error("", e);
}
return null;
}
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.java;
public final class Version {
private int major;
private int minor;
private int patch;
private String qualifier;
public Version(int major, int minor, int patch, String qualifier) {
super();
this.major = major;
this.minor = minor;
this.patch = patch;
this.qualifier = qualifier;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public String getQualifier() {
return qualifier;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020 Pivotal, Inc.
* Copyright (c) 2020, 2022 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,6 +21,7 @@ import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -44,7 +45,7 @@ public class AnnotationParamReconciler implements AnnotationReconciler {
this.reconciler = reconciler;
}
public void visit(IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
if (node instanceof SingleMemberAnnotation) {
visitSingleMemberAnnotation((SingleMemberAnnotation) node, typeBinding, problemCollector);
} else if (node instanceof NormalAnnotation) {

View File

@@ -1,12 +1,23 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.handlers;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public interface AnnotationReconciler {
void visit(IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector);
void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector);
}

View File

@@ -19,6 +19,9 @@ import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.SpringJavaProblemType;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.java.Version;
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
@@ -37,19 +40,24 @@ public class AutowiredConstructorReconciler implements AnnotationReconciler {
}
@Override
public void visit(IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
getSingleAutowiredConstructorDeclaringType(node, typeBinding).ifPresent(type -> {
ReconcileProblemImpl problem = new ReconcileProblemImpl(SpringJavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR, "Unnecesary @Autowired", node.getStartPosition(), node.getLength());
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(AutowiredConstructorReconciler.REMOVE_UNNECESSARY_AUTOWIRED_FROM_CONSTRUCTOR);
if (quickfixType != null) {
problem.addQuickfix(new QuickfixData<>(
quickfixType,
List.of(doc.getUri(), type.getQualifiedName()),
"Remove unnecessary @Autowired"
));
}
problemCollector.accept(problem);
});
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
Version version = SpringProjectUtil.getDependencyVersion(project, "spring-boot");
if (version.getMajor() >= 2) {
getSingleAutowiredConstructorDeclaringType(node, typeBinding).ifPresent(type -> {
ReconcileProblemImpl problem = new ReconcileProblemImpl(SpringJavaProblemType.JAVA_AUTOWIRED_CONSTRUCTOR, "Unnecesary @Autowired", node.getStartPosition(), node.getLength());
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(AutowiredConstructorReconciler.REMOVE_UNNECESSARY_AUTOWIRED_FROM_CONSTRUCTOR);
if (quickfixType != null) {
problem.addQuickfix(new QuickfixData<>(
quickfixType,
List.of(doc.getUri(), type.getQualifiedName()),
"Remove unnecessary @Autowired"
));
}
problemCollector.accept(problem);
});
}
}
static Optional<ITypeBinding> getSingleAutowiredConstructorDeclaringType(Annotation a, ITypeBinding type) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2020 Pivotal, Inc.
* Copyright (c) 2016, 2022 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,8 +20,6 @@ import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
import org.springframework.ide.vscode.boot.java.value.Constants;
import org.springframework.ide.vscode.commons.java.IJavaProject;
@@ -50,8 +48,6 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
public static final String SPRING_CONDITIONAL_ON_EXPRESSION = "org.springframework.boot.autoconfigure.condition.ConditionalOnExpression";
private static final Logger log = LoggerFactory.getLogger(BootJavaReconcileEngine.class);
private final JavaProjectFinder projectFinder;
private final CompilationUnitCache compilationUnitCache;
private final AnnotationReconciler[] reconcilers;
@@ -111,7 +107,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
compilationUnitCache.withCompilationUnit(project, uri, cu -> {
if (cu != null) {
reconcileAST(doc, cu, problemCollector);
reconcileAST(project, doc, cu, problemCollector);
}
return null;
@@ -123,13 +119,13 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
}
}
private void reconcileAST(IDocument doc, CompilationUnit cu, IProblemCollector problemCollector) {
private void reconcileAST(IJavaProject project, IDocument doc, CompilationUnit cu, IProblemCollector problemCollector) {
cu.accept(new ASTVisitor() {
@Override
public boolean visit(SingleMemberAnnotation node) {
try {
visitAnnotation(doc, node, problemCollector);
visitAnnotation(project, doc, node, problemCollector);
}
catch (Exception e) {
}
@@ -139,7 +135,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
@Override
public boolean visit(NormalAnnotation node) {
try {
visitAnnotation(doc, node, problemCollector);
visitAnnotation(project, doc, node, problemCollector);
}
catch (Exception e) {
}
@@ -149,7 +145,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
@Override
public boolean visit(MarkerAnnotation node) {
try {
visitAnnotation(doc, node, problemCollector);
visitAnnotation(project, doc, node, problemCollector);
}
catch (Exception e) {
}
@@ -159,12 +155,12 @@ public class BootJavaReconcileEngine implements IReconcileEngine {
});
}
protected void visitAnnotation(IDocument doc, Annotation node, IProblemCollector problemCollector) {
protected void visitAnnotation(IJavaProject project, IDocument doc, Annotation node, IProblemCollector problemCollector) {
ITypeBinding typeBinding = node.resolveTypeBinding();
if (typeBinding != null) {
for (int i = 0; i < reconcilers.length; i++) {
reconcilers[i].visit(doc, node, typeBinding, problemCollector);
reconcilers[i].visit(project, doc, node, typeBinding, problemCollector);
}
}
}