Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-73175] Expose exception for invalid reports #113

Merged
merged 8 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions src/main/java/edu/hm/hafner/coverage/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,6 @@ private Object readResolve() {
return this;
}

/**
* Create a new method node with the given method name and signature and add it to the list of children.
*
* @param methodName
* the method name
* @param signature
* the signature of the method
*
* @return the created and linked package node
*/
public MethodNode createMethodNode(final String methodName, final String signature) {
var fileNode = new MethodNode(methodName, signature);
addChild(fileNode);
return fileNode;
}

@Override
public boolean isAggregation() {
return false;
Expand Down
45 changes: 11 additions & 34 deletions src/main/java/edu/hm/hafner/coverage/FileNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public FileNode(final String name, final String relativePath) {
this(name, TreeString.valueOf(relativePath));
}

@Override
public String getId() {
return relativePath.toString() + getName();
}

/**
* Called after deserialization to retain backward compatibility.
*
Expand Down Expand Up @@ -114,14 +119,14 @@ protected boolean filterByRelativePath(final Collection<String> fileNames) {

@Override
public boolean matches(final Metric searchMetric, final String searchName) {
return super.matches(searchMetric, searchName)
|| getRelativePath().equals(searchName);
return getMetric().equals(searchMetric)
&& (getRelativePath().equals(searchName) || getName().equals(searchName));
}

@Override
public boolean matches(final Metric searchMetric, final int searchNameHashCode) {
return super.matches(searchMetric, searchNameHashCode)
|| getRelativePath().hashCode() == searchNameHashCode;
return getMetric().equals(searchMetric)
&& (getRelativePath().hashCode() == searchNameHashCode || getName().hashCode() == searchNameHashCode);
}

@Override
Expand Down Expand Up @@ -688,40 +693,12 @@ public List<Mutation> getMutations() {
}

/**
* Create a new class node with the given name and add it to the list of children.
*
* @param className
* the class name
*
* @return the created and linked class node
*/
public ClassNode createClassNode(final String className) {
var classNode = new ClassNode(className);
addChild(classNode);
return classNode;
}

/**
* Searches for the specified class node. If the class node is not found then a new class node will be created and
* linked to this file node.
*
* @param className
* the class name
*
* @return the created and linked class node
* @see #createClassNode(String)
*/
public ClassNode findOrCreateClassNode(final String className) {
return findClass(className).orElseGet(() -> createClassNode(className));
}

/**
* Returns the relative path of the file. If no relative path is set, then the name of this node is returned.
* Returns the relative path of the file.
*
* @return the relative path of the file
*/
public String getRelativePath() {
return StringUtils.defaultIfBlank(relativePath.toString(), getName());
return relativePath.toString();
}

@SuppressFBWarnings(value = "SECWF", justification = "False positive")
Expand Down
29 changes: 0 additions & 29 deletions src/main/java/edu/hm/hafner/coverage/ModuleNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,35 +121,6 @@ private PackageNode createPackageNode(final String subPackage, final List<Value>
return packageNode;
}

/**
* Create a new package node with the given name and add it to the list of children.
*
* @param packageName
* the package name
*
* @return the created and linked package node
*/
public PackageNode createPackageNode(final String packageName) {
var packageNode = new PackageNode(packageName);
addChild(packageNode);
return packageNode;
}

/**
* Searches for the specified package node. If the package node is not found, then a new package node will be created
* and linked to this module node.
*
* @param packageName
* the package name
*
* @return the existing or created package node
* @see #createPackageNode(String)
*/
public PackageNode findOrCreatePackageNode(final String packageName) {
var normalizedPackageName = PackageNode.normalizePackageName(packageName);
return findPackage(normalizedPackageName).orElseGet(() -> createPackageNode(normalizedPackageName));
}

@Override
public boolean isAggregation() {
return true;
Expand Down
155 changes: 145 additions & 10 deletions src/main/java/edu/hm/hafner/coverage/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.commons.lang3.tuple.ImmutablePair;

import edu.hm.hafner.util.Ensure;
import edu.hm.hafner.util.TreeString;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

Expand Down Expand Up @@ -66,6 +67,16 @@ public String getName() {
return name;
}

/**
* Returns the unique ID of this node. This ID must be unique for the direct children in this node. Other nodes in
* the tree hierarchy may reuse the same ID.
*
* @return the unique ID of this node
*/
public String getId() {
return getName();
}

void setName(final String name) { // Might be used during the deserialization of old reports
this.name = name;
}
Expand Down Expand Up @@ -162,9 +173,10 @@ public List<Node> getChildren() {
* the child to add
*/
public void addChild(final Node child) {
if (children.stream().anyMatch(node -> node.getName().equals(child.getName()))) {
if (hasChild(child.getId())) {
throw new IllegalArgumentException(
String.format("There is already a child %s with the name %s in %s", child, child.getName(), this));
String.format("There is already the same child %s with the name %s in %s",
child, child.getName(), this));
}

children.add(child);
Expand All @@ -188,7 +200,7 @@ protected void removeChild(final Node child) {
* @return {@code true} if this node has a child with the specified name, {@code false} otherwise
*/
public boolean hasChild(final String childName) {
return children.stream().map(Node::getName).anyMatch(childName::equals);
return children.stream().map(Node::getId).anyMatch(childName::equals);
}

/**
Expand All @@ -201,6 +213,16 @@ public void addAllChildren(final Collection<? extends Node> nodes) {
nodes.forEach(this::addChild);
}

/**
* Adds alls given nodes as children to the current node.
*
* @param nodes
* nodes to add
*/
public void addAllChildren(final Node... nodes) {
addAllChildren(List.of(nodes));
}

/**
* Returns the parent node.
*
Expand Down Expand Up @@ -433,15 +455,15 @@ public Optional<PackageNode> findPackage(final String searchName) {
}

/**
* Searches for a file within this node that has the given name.
* Searches for a file within this node that has the given relative path.
*
* @param searchName
* the name of the file
* @param searchPath
* the path of the file
*
* @return the first matching file or an empty result, if no such file exists
*/
public Optional<FileNode> findFile(final String searchName) {
return find(Metric.FILE, searchName).map(FileNode.class::cast);
public Optional<FileNode> findFile(final String searchPath) {
return find(Metric.FILE, searchPath).map(FileNode.class::cast);
}

/**
Expand Down Expand Up @@ -528,7 +550,7 @@ public Optional<Node> findByHashCode(final Metric searchMetric, final int search
* @return the result if found
*/
public boolean matches(final Metric searchMetric, final String searchName) {
return metric.equals(searchMetric) && name.equals(searchName);
return metric.equals(searchMetric) && getId().equals(searchName);
}

/**
Expand All @@ -542,7 +564,7 @@ public boolean matches(final Metric searchMetric, final String searchName) {
* @return the result if found
*/
public boolean matches(final Metric searchMetric, final int searchNameHashCode) {
return metric.equals(searchMetric) && name.hashCode() == searchNameHashCode;
return metric.equals(searchMetric) && getId().hashCode() == searchNameHashCode;
}

/**
Expand Down Expand Up @@ -866,6 +888,119 @@ private Optional<Node> filterTreeByMapping(final Function<Node, Optional<Node>>
return Optional.of(copy);
}

/**
* Creates a new method node with the given method name and signature.
* Then the newly created node is added to this list of children.
*
* @param methodName
* the method name
* @param signature
* the signature of the method
*
* @return the created and linked node
*/
public MethodNode createMethodNode(final String methodName, final String signature) {
return addChildNode(new MethodNode(methodName, signature));
}

/**
* Creates a new class node with the given name.
* Then the newly created node is added to this list of children.
*
* @param className
* the class name
*
* @return the created and linked node
*/
public ClassNode createClassNode(final String className) {
return addChildNode(new ClassNode(className));
}

/**
* Creates a new file node with the given file name and path.
* Then the newly created node is added to this list of children.
*
* @param fileName
* the file name
* @param relativePath
* the relative path of the file
*
* @return the created and linked node
*/
public FileNode createFileNode(final String fileName, final TreeString relativePath) {
return addChildNode(new FileNode(fileName, relativePath));
}

/**
* Creates a new package node with the given name.
* Then the newly created node is added to this list of children.
*
* @param packageName
* the package name
*
* @return the created and linked node
*/
public PackageNode createPackageNode(final String packageName) {
return addChildNode(new PackageNode(packageName));
}

private <T extends Node> T addChildNode(final T child) {
addChild(child);
return child;
}

/**
* Searches for the specified class node. If the class node is not found, then a new class node will be created and
* linked to this node.
*
* @param className
* the class name
*
* @return the created and linked class node
* @see #createClassNode(String)
*/
public ClassNode findOrCreateClassNode(final String className) {
return findClass(className).orElseGet(() -> createClassNode(className));
}

/**
* Searches for the specified file node. If the file node is not found, then a new file node will be created and
* linked to this node.
*
* @param fileName
* the file name
* @param relativePath
* the relative path of the file
*
* @return the existing or created file node
* @see #createFileNode(String, TreeString)
*/
public FileNode findOrCreateFileNode(final String fileName, final TreeString relativePath) {
return findFile(fileName, relativePath.toString()).orElseGet(() -> createFileNode(fileName, relativePath));
}

/**
* Searches for the specified package node. If the package node is not found, then a new package node will be created
* and linked to this module node.
*
* @param packageName
* the package name
*
* @return the existing or created package node
* @see #createPackageNode(String)
*/
public PackageNode findOrCreatePackageNode(final String packageName) {
var normalizedPackageName = PackageNode.normalizePackageName(packageName);

return findPackage(normalizedPackageName).orElseGet(() -> createPackageNode(normalizedPackageName));
}

private Optional<FileNode> findFile(final String fileName, final String relativePath) {
return getAllFileNodes().stream().filter(fileNode ->
fileNode.getName().equals(fileName)
&& fileNode.getRelativePath().equals(relativePath)).findAny();
}

/**
* Returns whether this node is an aggregation of other nodes. Aggregation nodes do not store values, they rather
* aggregate the values of their children.
Expand Down
Loading
Loading