Browse Source

SONAR-6664 add PathAwareVisitor to visit a Component tree

tags/5.2-RC1
Sébastien Lesaint 9 years ago
parent
commit
d4c10655a1
18 changed files with 578 additions and 19 deletions
  1. 4
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java
  2. 1
    5
      server/sonar-server/src/main/java/org/sonar/server/computation/component/DepthTraversalTypeAwareVisitor.java
  3. 295
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/component/PathAwareVisitor.java
  4. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java
  5. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeIssueMeasuresStep.java
  6. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java
  7. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java
  8. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileSourcesStep.java
  9. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java
  10. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistNumberOfDaysSinceLastCommitStep.java
  11. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java
  12. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java
  13. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateMeasuresStep.java
  14. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java
  15. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java
  16. 264
    0
      server/sonar-server/src/test/java/org/sonar/server/computation/component/PathAwareVisitorTest.java
  17. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/computation/component/PostOrderDepthTraversalTypeAwareVisitorTest.java
  18. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/computation/component/PreOrderDepthTraversalTypeAwareVisitorTest.java

+ 4
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java View File

@@ -21,4 +21,8 @@ package org.sonar.server.computation.component;

public interface ComponentVisitor {
void visit(Component tree);

enum Order {
PRE_ORDER, POST_ORDER
}
}

+ 1
- 5
server/sonar-server/src/main/java/org/sonar/server/computation/component/DepthTraversalTypeAwareVisitor.java View File

@@ -53,7 +53,7 @@ public abstract class DepthTraversalTypeAwareVisitor implements TypeAwareVisitor
}
}

protected void visitNode(Component component) {
private void visitNode(Component component) {
visitAny(component);
switch (component.getType()) {
case PROJECT:
@@ -110,8 +110,4 @@ public abstract class DepthTraversalTypeAwareVisitor implements TypeAwareVisitor
public void visitAny(Component component) {
// empty implementation, meant to be override at will by subclasses
}

public enum Order {
PRE_ORDER, POST_ORDER
}
}

+ 295
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/component/PathAwareVisitor.java View File

@@ -0,0 +1,295 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.computation.component;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;

import static java.util.Objects.requireNonNull;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* A ComponentVisitor which provide access to a representation of the path from the root to the currently visited
* Component. It also provides a way to have an object associated to each Component and access it and all of its
* parent's.
* As for {@link DepthTraversalTypeAwareVisitor}, this visitor supports max depth visit and ordering.
*/
public abstract class PathAwareVisitor<T> implements ComponentVisitor {
private final Component.Type maxDepth;
private final Order order;
private final StackElementFactory<T> factory;
private final DequeBasedPath<T> stack = new DequeBasedPath<>();

public PathAwareVisitor(Component.Type maxDepth, Order order, StackElementFactory<T> factory) {
this.maxDepth = requireNonNull(maxDepth);
this.order = requireNonNull(order);
this.factory = requireNonNull(factory, "Factory can not be null");
}

@Override
public void visit(Component component) {
if (component.getType().isDeeperThan(maxDepth)) {
return;
}

stack.add(new PathElementImpl<>(component, createForComponent(component)));

if (order == PRE_ORDER) {
visitNode(component);
}

visitChildren(component);

if (order == POST_ORDER) {
visitNode(component);
}

stack.pop();
}

private T createForComponent(Component component) {
switch (component.getType()) {
case PROJECT:
return factory.createForProject(component);
case MODULE:
return factory.createForModule(component);
case DIRECTORY:
return factory.createForDirectory(component);
case FILE:
return factory.createForFile(component);
default:
return factory.createForUnknown(component);
}
}

private void visitChildren(Component component) {
if (component.getType() != maxDepth) {
for (Component child : component.getChildren()) {
visit(child);
}
}
}

private void visitNode(Component component) {
visitAny(component, stack);
switch (component.getType()) {
case PROJECT:
visitProject(component, stack);
break;
case MODULE:
visitModule(component, stack);
break;
case DIRECTORY:
visitDirectory(component, stack);
break;
case FILE:
visitFile(component, stack);
break;
default:
visitUnknown(component, stack);
}
}

protected void visitProject(Component project, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

protected void visitModule(Component module, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

protected void visitDirectory(Component directory, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

protected void visitFile(Component file, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

protected void visitUnknown(Component unknownComponent, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

protected void visitAny(Component component, Path<T> path) {
// empty implementation, meant to be override at will by subclasses
}

public interface StackElementFactory<T> {
T createForProject(Component project);

T createForModule(Component module);

T createForDirectory(Component directory);

T createForFile(Component file);

T createForUnknown(Component file);
}

/**
* A Simple implementation which uses the same factory method for all types which can be implemented by subclasses:
* {@link #createForAny(Component)}.
*/
public abstract static class SimpleStackElementFactory<T> implements StackElementFactory<T> {

public abstract T createForAny(Component component);

@Override
public T createForProject(Component project) {
return createForAny(project);
}

@Override
public T createForModule(Component module) {
return createForAny(module);
}

@Override
public T createForDirectory(Component directory) {
return createForAny(directory);
}

@Override
public T createForFile(Component file) {
return createForAny(file);
}

@Override
public T createForUnknown(Component file) {
return createForAny(file);
}
}

private static class DequeBasedPath<T> implements Path<T>, Iterable<PathElement<T>> {
private final Deque<PathElement<T>> deque = new ArrayDeque<>();

@Override
public T current() {
return deque.getFirst().getElement();
}

@Override
public T parent() {
Iterator<PathElement<T>> iterator = deque.iterator();
if (iterator.hasNext()) {
iterator.next();
if (iterator.hasNext()) {
return iterator.next().getElement();
}
}
throw new NoSuchElementException("Path is either empty or has only one element. There is no parent");
}

@Override
public boolean isRoot() {
return deque.size() == 1;
}

@Override
public T root() {
return deque.getLast().getElement();
}

@Override
public Iterator<PathElement<T>> iterator() {
return deque.iterator();
}

@Override
public Iterable<PathElement<T>> getCurrentPath() {
return this;
}

public void add(PathElement<T> pathElement) {
deque.addFirst(pathElement);
}

public PathElement<T> pop() {
return deque.pop();
}
}

public interface Path<T> {
/**
* The stacked element of the current Component.
*/
T current();

/**
* Tells whether the current Component is the root of the tree.
*/
boolean isRoot();

/**
* The stacked element of the parent of the current Component.
*
* @throws NoSuchElementException if the current Component is the root of the tree
* @see #isRoot()
*/
T parent();

/**
* The stacked element of the root of the tree.
*/
T root();

/**
* The path to the current Component as an Iterable of {@link PathAwareVisitor.PathElement} which starts with
* the {@link PathAwareVisitor.PathElement} of the current Component and ends with the
* {@link PathAwareVisitor.PathElement} of the root of the tree.
*/
Iterable<PathElement<T>> getCurrentPath();
}

public interface PathElement<T> {
/**
* The Component on the path.
*/
Component getComponent();

/**
* The stacked element for the Component of this PathElement.
*/
T getElement();
}

private static final class PathElementImpl<T> implements PathElement<T> {
private final Component component;
private final T element;

private PathElementImpl(Component component, T element) {
this.component = component;
this.element = element;
}

@Override
public Component getComponent() {
return component;
}

@Override
public T getElement() {
return element;
}
}
}

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java View File

@@ -23,7 +23,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;

/**
* Holds the reference to the root of the {@link Component} tree for the current CE run.

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeIssueMeasuresStep.java View File

@@ -69,7 +69,7 @@ import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY;
import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY;
import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY;
import static org.sonar.server.computation.component.Component.Type.FILE;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;

/**
* Computes metrics related to number of issues.

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java View File

@@ -46,7 +46,7 @@ import org.sonar.server.computation.period.Period;
import org.sonar.server.computation.period.PeriodsHolder;
import org.sonar.server.db.DbClient;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* Set variations on all numeric measures found in the repository.

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java View File

@@ -36,7 +36,7 @@ import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.db.DbClient;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* Persist duplications into

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileSourcesStep.java View File

@@ -49,7 +49,7 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.source.db.FileSourceDb;
import org.sonar.server.util.CloseableIterator;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

public class PersistFileSourcesStep implements ComputationStep {


+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java View File

@@ -44,7 +44,7 @@ import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.db.DbClient;

import static com.google.common.collect.FluentIterable.from;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

public class PersistMeasuresStep implements ComputationStep {


+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistNumberOfDaysSinceLastCommitStep.java View File

@@ -39,7 +39,7 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.source.index.SourceLineIndex;

import static com.google.common.base.Objects.firstNonNull;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

public class PersistNumberOfDaysSinceLastCommitStep implements ComputationStep {


+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java View File

@@ -41,7 +41,7 @@ import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.db.DbClient;

import static com.google.common.collect.Sets.newHashSet;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* Persist project and module links

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java View File

@@ -34,7 +34,7 @@ import org.sonar.server.computation.qualitygate.QualityGate;
import org.sonar.server.computation.qualitygate.QualityGateService;

import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* This step retrieves the QualityGate for the current {@link ReportQueue.Item} and stores it in

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateMeasuresStep.java View File

@@ -44,7 +44,7 @@ import org.sonar.server.computation.qualitygate.QualityGate;
import org.sonar.server.computation.qualitygate.QualityGateHolder;

import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* This step:

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java View File

@@ -42,7 +42,7 @@ import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.qualityprofile.QPMeasureData;
import org.sonar.server.computation.qualityprofile.QualityProfile;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;

public class QualityProfileEventsStep implements ComputationStep {
private final TreeRootHolder treeRootHolder;

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java View File

@@ -29,7 +29,7 @@ import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor;
import org.sonar.server.computation.component.TreeRootHolder;

import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;

public class TreeRootHolderRule implements TestRule, TreeRootHolder {
private Component root;

+ 264
- 0
server/sonar-server/src/test/java/org/sonar/server/computation/component/PathAwareVisitorTest.java View File

@@ -0,0 +1,264 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.computation.component;

import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.junit.Test;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.ImmutableList.of;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
import static org.sonar.server.computation.component.Component.Type.FILE;
import static org.sonar.server.computation.component.Component.Type.MODULE;
import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

public class PathAwareVisitorTest {

private static final int ROOT_REF = 1;
private static final DumbComponent SOME_TREE_ROOT = DumbComponent.builder(PROJECT, ROOT_REF)
.addChildren(
DumbComponent.builder(MODULE, 11)
.addChildren(
DumbComponent.builder(DIRECTORY, 111)
.addChildren(
DumbComponent.builder(FILE, 1111).build(),
DumbComponent.builder(FILE, 1112).build()
)
.build(),
DumbComponent.builder(DIRECTORY, 112)
.addChildren(
DumbComponent.builder(FILE, 1121).build()
)
.build())
.build(),
DumbComponent.builder(MODULE, 12)
.addChildren(
DumbComponent.builder(DIRECTORY, 121)
.addChildren(
DumbComponent.builder(FILE, 1211).build()
)
.build()
).build()
).build();

@Test
public void verify_preOrder() {
TestPathAwareVisitor underTest = new TestPathAwareVisitor(PRE_ORDER);
underTest.visit(SOME_TREE_ROOT);

Iterator<CallRecord> expected = of(
newCallRecord("visitAny", 1, null, of(1)),
newCallRecord("visitProject", 1, null, of(1)),
newCallRecord("visitAny", 11, 1, of(11, 1)),
newCallRecord("visitModule", 11, 1, of(11, 1)),
newCallRecord("visitAny", 111, 11, of(111, 11, 1)),
newCallRecord("visitDirectory", 111, 11, of(111, 11, 1)),
newCallRecord("visitAny", 1111, 111, of(1111, 111, 11, 1)),
newCallRecord("visitFile", 1111, 111, of(1111, 111, 11, 1)),
newCallRecord("visitAny", 1112, 111, of(1112, 111, 11, 1)),
newCallRecord("visitFile", 1112, 111, of(1112, 111, 11, 1)),
newCallRecord("visitAny", 112, 11, of(112, 11, 1)),
newCallRecord("visitDirectory", 112, 11, of(112, 11, 1)),
newCallRecord("visitAny", 1121, 112, of(1121, 112, 11, 1)),
newCallRecord("visitFile", 1121, 112, of(1121, 112, 11, 1)),
newCallRecord("visitAny", 12, 1, of(12, 1)),
newCallRecord("visitModule", 12, 1, of(12, 1)),
newCallRecord("visitAny", 121, 12, of(121, 12, 1)),
newCallRecord("visitDirectory", 121, 12, of(121, 12, 1)),
newCallRecord("visitAny", 1211, 121, of(1211, 121, 12, 1)),
newCallRecord("visitFile", 1211, 121, of(1211, 121, 12, 1))
).iterator();
verifyCallRecords(expected, underTest.callsRecords.iterator());
}

@Test
public void verify_postOrder() {
TestPathAwareVisitor underTest = new TestPathAwareVisitor(POST_ORDER);
underTest.visit(SOME_TREE_ROOT);

Iterator<CallRecord> expected = of(
newCallRecord("visitAny", 1111, 111, of(1111, 111, 11, 1)),
newCallRecord("visitFile", 1111, 111, of(1111, 111, 11, 1)),
newCallRecord("visitAny", 1112, 111, of(1112, 111, 11, 1)),
newCallRecord("visitFile", 1112, 111, of(1112, 111, 11, 1)),
newCallRecord("visitAny", 111, 11, of(111, 11, 1)),
newCallRecord("visitDirectory", 111, 11, of(111, 11, 1)),
newCallRecord("visitAny", 1121, 112, of(1121, 112, 11, 1)),
newCallRecord("visitFile", 1121, 112, of(1121, 112, 11, 1)),
newCallRecord("visitAny", 112, 11, of(112, 11, 1)),
newCallRecord("visitDirectory", 112, 11, of(112, 11, 1)),
newCallRecord("visitAny", 11, 1, of(11, 1)),
newCallRecord("visitModule", 11, 1, of(11, 1)),
newCallRecord("visitAny", 1211, 121, of(1211, 121, 12, 1)),
newCallRecord("visitFile", 1211, 121, of(1211, 121, 12, 1)),
newCallRecord("visitAny", 121, 12, of(121, 12, 1)),
newCallRecord("visitDirectory", 121, 12, of(121, 12, 1)),
newCallRecord("visitAny", 12, 1, of(12, 1)),
newCallRecord("visitModule", 12, 1, of(12, 1)),
newCallRecord("visitAny", 1, null, of(1)),
newCallRecord("visitProject", 1, null, of(1))
).iterator();
verifyCallRecords(expected, underTest.callsRecords.iterator());
}

private static void verifyCallRecords(Iterator<CallRecord> expected, Iterator<CallRecord> actual) {
while (expected.hasNext()) {
assertThat(actual.next()).isEqualTo(expected.next());
}
}

private static CallRecord newCallRecord(String method, int currentRef, @Nullable Integer parentRef, List<Integer> path) {
return new CallRecord(method, currentRef, currentRef, parentRef, ROOT_REF, path);
}

private static class TestPathAwareVisitor extends PathAwareVisitor<Integer> {
private final List<CallRecord> callsRecords = new ArrayList<>();

public TestPathAwareVisitor(ComponentVisitor.Order order) {
super(FILE, order, new SimpleStackElementFactory<Integer>() {
@Override
public Integer createForAny(Component component) {
return component.getRef();
}
});
}

@Override
protected void visitProject(Component project, Path<Integer> path) {
callsRecords.add(newCallRecord(project, path, "visitProject"));
}

@Override
protected void visitModule(Component module, Path<Integer> path) {
callsRecords.add(newCallRecord(module, path, "visitModule"));
}

@Override
protected void visitDirectory(Component directory, Path<Integer> path) {
callsRecords.add(newCallRecord(directory, path, "visitDirectory"));
}

@Override
protected void visitFile(Component file, Path<Integer> path) {
callsRecords.add(newCallRecord(file, path, "visitFile"));
}

@Override
protected void visitUnknown(Component unknownComponent, Path<Integer> path) {
callsRecords.add(newCallRecord(unknownComponent, path, "visitUnknown"));
}

@Override
protected void visitAny(Component component, Path<Integer> path) {
callsRecords.add(newCallRecord(component, path, "visitAny"));
}

private static CallRecord newCallRecord(Component project, Path<Integer> path, String method) {
return new CallRecord(method, project.getRef(), path.current(), getParent(path), path.root(),
toValueList(path));
}

private static List<Integer> toValueList(Path<Integer> path) {
return from(path.getCurrentPath()).transform(new Function<PathElement<Integer>, Integer>() {
@Nonnull
@Override
public Integer apply(@Nonnull PathElement<Integer> input) {
return input.getElement();
}
}).toList();
}

private static Integer getParent(Path<Integer> path) {
try {
Integer parent = path.parent();
checkArgument(parent != null, "Path.parent returned a null value!");
return parent;
} catch (NoSuchElementException e) {
return null;
}
}
}

private static class CallRecord {
private final String method;
private final int ref;
private final int current;
@CheckForNull
private final Integer parent;
private final int root;
private final List<Integer> path;

private CallRecord(String method, int ref, int current, @Nullable Integer parent, int root, List<Integer> path) {
this.method = method;
this.ref = ref;
this.current = current;
this.parent = parent;
this.root = root;
this.path = path;
}

@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CallRecord that = (CallRecord) o;
return Objects.equals(ref, that.ref) &&
Objects.equals(current, that.current) &&
Objects.equals(root, that.root) &&
Objects.equals(method, that.method) &&
Objects.equals(parent, that.parent) &&
Objects.equals(path, that.path);
}

@Override
public int hashCode() {
return Objects.hash(method, ref, current, parent, root, path);
}

@Override
public String toString() {
return "{" +
"method='" + method + '\'' +
", ref=" + ref +
", current=" + current +
", parent=" + parent +
", root=" + root +
", path=" + path +
'}';
}
}

}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/computation/component/PostOrderDepthTraversalTypeAwareVisitorTest.java View File

@@ -29,7 +29,7 @@ import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
import static org.sonar.server.computation.component.Component.Type.FILE;
import static org.sonar.server.computation.component.Component.Type.MODULE;
import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;

public class PostOrderDepthTraversalTypeAwareVisitorTest {


+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/computation/component/PreOrderDepthTraversalTypeAwareVisitorTest.java View File

@@ -29,7 +29,7 @@ import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
import static org.sonar.server.computation.component.Component.Type.FILE;
import static org.sonar.server.computation.component.Component.Type.MODULE;
import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

public class PreOrderDepthTraversalTypeAwareVisitorTest {


Loading…
Cancel
Save