package org.sonar.server.computation.task.projectanalysis.component;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import java.util.function.Function;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.scanner.protocol.output.ScannerReport;
import static com.google.common.collect.Iterables.toArray;
import static org.sonar.core.util.stream.Collectors.toList;
public class ComponentRootBuilder {
+ private static final String DEFAULT_PROJECT_VERSION = "not provided";
+
+ /**
+ * Will supply the UUID for any component in the tree, given it's key.
+ * <p>
+ * The String argument of the {@link Function#apply(Object)} method is the component's key.
+ * </p>
+ */
private final Function<String, String> uuidSupplier;
+ /**
+ * Will supply the {@link ScannerReport.Component} of all the components in the component tree as we crawl it from the
+ * root.
+ * <p>
+ * The Integer argument of the {@link Function#apply(Object)} method is the component's ref.
+ * </p>
+ */
private final Function<Integer, ScannerReport.Component> scannerComponentSupplier;
+ /**
+ * Will supply the ComponentDto of the project (if it exists) if we need it to get the name of the project
+ *
+ * @see #nameOfProject(ScannerReport.Component, String, Supplier)
+ */
private final Supplier<Optional<ComponentDto>> projectDtoSupplier;
+ /**
+ * Will supply the SnapshotDto of the base analysis of the project (if it exists) if we need it to get the version
+ * of the project.
+ * <p>
+ * The String argument of the {@link Function#apply(Object)} method is the project's UUID.
+ * </p>
+ *
+ * @see #createProjectVersion(ScannerReport.Component, String, Function)
+ */
+ private final Function<String, Optional<SnapshotDto>> analysisSupplier;
@CheckForNull
private final String branch;
public ComponentRootBuilder(@Nullable String branch,
Function<String, String> uuidSupplier,
Function<Integer, ScannerReport.Component> scannerComponentSupplier,
- Supplier<Optional<ComponentDto>> projectDtoSupplier) {
+ Supplier<Optional<ComponentDto>> projectDtoSupplier,
+ Function<String, Optional<SnapshotDto>> analysisSupplier) {
this.uuidSupplier = uuidSupplier;
this.scannerComponentSupplier = scannerComponentSupplier;
this.projectDtoSupplier = projectDtoSupplier;
this.branch = branch;
+ this.analysisSupplier = analysisSupplier;
}
public Component build(ScannerReport.Component reportProject, String projectKey) {
private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String latestModuleKey) {
switch (reportComponent.getType()) {
case PROJECT:
- return createCommonBuilder(reportComponent, latestModuleKey, latestModuleKey)
- .setName(nameOfProject(reportComponent, latestModuleKey, projectDtoSupplier))
- .build();
+ return buildProjectComponent(reportComponent, latestModuleKey);
case MODULE:
String moduleKey = createKey(reportComponent.getKey(), branch);
return buildOtherComponent(reportComponent, moduleKey, moduleKey);
}
}
+ private ComponentImpl buildProjectComponent(ScannerReport.Component reportComponent, String latestModuleKey) {
+ ComponentImpl.Builder builder = createCommonBuilder(reportComponent, latestModuleKey, latestModuleKey);
+ return builder
+ .setName(nameOfProject(reportComponent, latestModuleKey, projectDtoSupplier))
+ .setReportAttributes(createProjectReportAttributes(reportComponent, builder.getUuid(), analysisSupplier))
+ .build();
+ }
+
private ComponentImpl buildOtherComponent(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) {
return createCommonBuilder(reportComponent, componentKey, latestModuleKey)
.setName(nameOfOthers(reportComponent, componentKey))
+ .setReportAttributes(createOtherReportAttributes(reportComponent))
.build();
}
.setKey(componentKey)
.setDescription(trimToNull(reportComponent.getDescription()))
.setFileAttributes(createFileAttributes(reportComponent))
- .setReportAttributes(createReportAttributes(reportComponent))
.addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class));
}
}
@VisibleForTesting
- static ReportAttributes createReportAttributes(ScannerReport.Component component) {
- return ReportAttributes.newBuilder(component.getRef())
- .setPath(trimToNull(component.getPath()))
+ static ReportAttributes createProjectReportAttributes(ScannerReport.Component component,
+ String projectUuid, Function<String, Optional<SnapshotDto>> analysisSupplier) {
+ return createCommonBuilder(component)
+ .setVersion(createProjectVersion(component, projectUuid, analysisSupplier))
+ .build();
+ }
+
+ private static String createProjectVersion(ScannerReport.Component component,
+ String projectUuid, Function<String, Optional<SnapshotDto>> analysisSupplier) {
+ String version = trimToNull(component.getVersion());
+ if (version != null) {
+ return version;
+ }
+ Optional<SnapshotDto> snapshotDto = analysisSupplier.apply(projectUuid);
+ if (snapshotDto.isPresent()) {
+ return MoreObjects.firstNonNull(snapshotDto.get().getVersion(), DEFAULT_PROJECT_VERSION);
+ }
+ return DEFAULT_PROJECT_VERSION;
+ }
+
+ @VisibleForTesting
+ static ReportAttributes createOtherReportAttributes(ScannerReport.Component component) {
+ return createCommonBuilder(component)
.setVersion(trimToNull(component.getVersion()))
.build();
}
+ private static ReportAttributes.Builder createCommonBuilder(ScannerReport.Component component) {
+ return ReportAttributes.newBuilder(component.getRef())
+ .setPath(trimToNull(component.getPath()));
+ }
+
@VisibleForTesting
@CheckForNull
static FileAttributes createFileAttributes(ScannerReport.Component component) {
*/
package org.sonar.server.computation.task.projectanalysis.step;
+import com.google.common.base.Optional;
+import java.util.Objects;
+import java.util.function.Function;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.SnapshotDto;
import org.sonar.server.computation.task.projectanalysis.component.UuidFactory;
import org.sonar.server.computation.task.step.ComputationStep;
+import static com.google.common.base.Preconditions.checkState;
import static org.sonar.core.component.ComponentKeys.createKey;
/**
UuidFactory uuidFactory = new UuidFactory(dbClient, projectKey);
try (DbSession dbSession = dbClient.openSession(false)) {
+ BaseAnalysisSupplier baseAnalysisSupplier = new BaseAnalysisSupplier(dbClient, dbSession);
ComponentRootBuilder rootBuilder = new ComponentRootBuilder(branch,
uuidFactory::getOrCreateForKey,
reportReader::readComponent,
- () -> dbClient.componentDao().selectByKey(dbSession, projectKey));
+ () -> dbClient.componentDao().selectByKey(dbSession, projectKey),
+ baseAnalysisSupplier);
Component project = rootBuilder.build(reportProject, projectKey);
treeRootHolder.setRoot(project);
- setBaseAnalysis(dbSession, project.getUuid());
+ analysisMetadataHolder.setBaseAnalysis(toAnalysis(baseAnalysisSupplier.apply(project.getUuid())));
}
}
- private void setBaseAnalysis(DbSession dbSession, String projectUuid) {
- SnapshotDto snapshotDto = dbClient.snapshotDao().selectAnalysisByQuery(dbSession,
- new SnapshotQuery()
- .setComponentUuid(projectUuid)
- .setIsLast(true));
- analysisMetadataHolder.setBaseAnalysis(toAnalysis(snapshotDto));
+ /**
+ * A supplier of the base analysis of the project (if it exists) that will cache the retrieved SnapshotDto and
+ * implement a sanity check to ensure it is always call with the same UUID value (since it's the project's UUID, it
+ * is unique for a whole task).
+ */
+ private static final class BaseAnalysisSupplier implements Function<String, Optional<SnapshotDto>> {
+ private final DbClient dbClient;
+ private final DbSession dbSession;
+ private String projectUuid = null;
+ private Optional<SnapshotDto> cache = null;
+
+ private BaseAnalysisSupplier(DbClient dbClient, DbSession dbSession) {
+ this.dbClient = dbClient;
+ this.dbSession = dbSession;
+ }
+
+ @Override
+ public Optional<SnapshotDto> apply(String projectUuid) {
+ if (this.cache == null) {
+ this.cache = Optional.fromNullable(
+ dbClient.snapshotDao().selectAnalysisByQuery(
+ dbSession,
+ new SnapshotQuery()
+ .setComponentUuid(projectUuid)
+ .setIsLast(true)));
+ this.projectUuid = projectUuid;
+ } else {
+ checkState(
+ Objects.equals(this.projectUuid, projectUuid),
+ "BaseAnalysisSupplier called with different project uuid values. First one was %s but current one is %s",
+ this.projectUuid, projectUuid);
+ }
+ return this.cache;
+ }
}
@CheckForNull
- private static Analysis toAnalysis(@Nullable SnapshotDto snapshotDto) {
- if (snapshotDto == null) {
- return null;
+ private static Analysis toAnalysis(Optional<SnapshotDto> snapshotDto) {
+ if (snapshotDto.isPresent()) {
+ SnapshotDto dto = snapshotDto.get();
+ return new Analysis.Builder()
+ .setId(dto.getId())
+ .setUuid(dto.getUuid())
+ .setCreatedAt(dto.getCreatedAt())
+ .build();
}
- return new Analysis.Builder()
- .setId(snapshotDto.getId())
- .setUuid(snapshotDto.getUuid())
- .setCreatedAt(snapshotDto.getCreatedAt())
- .build();
+ return null;
}
}
import org.junit.Test;
import org.junit.rules.ExternalResource;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.scanner.protocol.output.ScannerReport;
import static com.google.common.base.Preconditions.checkArgument;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNSET;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createFileAttributes;
-import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createReportAttributes;
+import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createOtherReportAttributes;
+import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createProjectReportAttributes;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
public class ComponentRootBuilderTest {
private static final String FILE_KEY = MODULE_KEY + ":" + FILE_PATH;
private static final ComponentDto PROJECT_DTO = new ComponentDto().setName("name in db");
private static final Supplier<Optional<ComponentDto>> NO_COMPONENT_DTO_FOR_PROJECT = Optional::absent;
+ private static final Function<String, Optional<SnapshotDto>> NO_BASEANALYSIS = (projectUuid) -> Optional.absent();
private static final Supplier<Optional<ComponentDto>> COMPONENT_DTO_FOR_PROJECT = () -> Optional.of(PROJECT_DTO);
private static final EnumSet<ScannerReport.Component.ComponentType> REPORT_TYPES = EnumSet.of(
PROJECT, MODULE, DIRECTORY, FILE);
+ private static final String PROJECT_UUID = "project uuid";
+ private static final String DEFAULT_VERSION = "not provided";
@Rule
public ScannerComponentProvider scannerComponentProvider = new ScannerComponentProvider();
- private ComponentRootBuilder underTest = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT);
+ private ComponentRootBuilder underTest = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT, NO_BASEANALYSIS);
@Test
public void build_throws_IAE_for_all_types_but_PROJECT_MODULE_DIRECTORY_FILE() {
@Test
public void name_of_project_is_name_in_Scanner_Component_when_set_even_if_there_is_a_ComponentDto() {
String expected = "the name";
- Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT)
+ Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT, NO_BASEANALYSIS)
.build(newBuilder().setType(PROJECT).setName(expected).build(), PROJECT_KEY);
assertThat(root.getName()).isEqualTo(expected);
}
@Test
public void name_of_project_is_name_of_ComponentDto_when_name_is_unset_in_Scanner_Component_and_there_is_a_ComponentDto() {
- Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT)
+ Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT, NO_BASEANALYSIS)
.build(newBuilder().setType(PROJECT).build(), PROJECT_KEY);
assertThat(root.getName()).isEqualTo(PROJECT_DTO.name());
@Test
public void name_of_project_is_name_of_ComponentDto_when_name_is_empty_in_Scanner_Component_and_there_is_a_ComponentDto() {
- Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT)
+ Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT, NO_BASEANALYSIS)
.build(newBuilder().setType(PROJECT).setName("").build(), PROJECT_KEY);
assertThat(root.getName()).isEqualTo(PROJECT_DTO.name());
scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setPath(FILE_PATH));
String branch = "BRANCH";
- ComponentRootBuilder builder = new ComponentRootBuilder(branch, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT);
+ ComponentRootBuilder builder = new ComponentRootBuilder(branch, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT, NO_BASEANALYSIS);
Component root = builder.build(project, PROJECT_KEY);
assertThat(root.getKey()).isEqualTo(PROJECT_KEY);
assertThat(componentsByRef.get(38).getKey()).startsWith("module 3" + ":");
}
+ @Test
+ public void version_of_project_is_set_to_default_value_when_unset_in_Scanner_Component_and_no_base_analysis() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).build();
+
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider,
+ NO_COMPONENT_DTO_FOR_PROJECT, this::noBaseAnalysisButValidateProjectUuidArgument);
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(DEFAULT_VERSION);
+ }
+
+ @Test
+ public void version_of_project_is_set_to_default_value_when_empty_in_Scanner_Component_and_no_base_analysis() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).setVersion("").build();
+
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider,
+ NO_COMPONENT_DTO_FOR_PROJECT, this::noBaseAnalysisButValidateProjectUuidArgument);
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(DEFAULT_VERSION);
+ }
+
+ private Optional<SnapshotDto> noBaseAnalysisButValidateProjectUuidArgument(String projectUuid) {
+ assertThat(projectUuid).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY));
+ return Optional.absent();
+ }
+
+ @Test
+ public void version_of_project_is_set_to_base_analysis_version_when_unset_in_Scanner_Component_and_base_analysis_has_a_version() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).build();
+
+ String expected = "some version";
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider,
+ NO_COMPONENT_DTO_FOR_PROJECT,
+ (projectUuid) -> {
+ assertThat(projectUuid).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY));
+ return Optional.of(new SnapshotDto().setVersion(expected));
+ });
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(expected);
+ }
+
+ @Test
+ public void version_of_project_is_set_to_base_analysis_version_when_empty_in_Scanner_Component_and_base_analysis_has_a_version() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).setVersion("").build();
+
+ String expected = "some version";
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT,
+ (projectUuid) -> {
+ assertThat(projectUuid).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY));
+ return Optional.of(new SnapshotDto().setVersion(expected));
+ });
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(expected);
+ }
+
+ @Test
+ public void version_of_project_is_set_to_default_value_when_unset_in_Scanner_Component_and_base_analysis_has_no_version() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).build();
+
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider,
+ NO_COMPONENT_DTO_FOR_PROJECT,
+ (projectUuid) -> {
+ assertThat(projectUuid).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY));
+ return Optional.of(new SnapshotDto());
+ });
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(DEFAULT_VERSION);
+ }
+
+ @Test
+ public void version_of_project_is_set_to_default_value_when_empty_in_Scanner_Component_and_base_analysis_has_no_version() {
+ ScannerReport.Component project = newBuilder().setType(PROJECT).setVersion("").build();
+
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT,
+ (projectUuid) -> {
+ assertThat(projectUuid).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY));
+ return Optional.of(new SnapshotDto());
+ });
+
+ Component root = builder.build(project, PROJECT_KEY);
+ assertThat(root.getReportAttributes().getVersion()).isEqualTo(DEFAULT_VERSION);
+ }
+
+ @Test
+ public void version_of_project_is_set_to_value_in_Scanner_Component_when_set() {
+ String expected = "some version";
+ ScannerReport.Component project = newBuilder().setType(PROJECT).setVersion(expected).build();
+ ComponentRootBuilder builder = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT,
+ this::noBaseAnalysisButEnsureIsNotCalled);
+
+ assertThat(builder.build(project, PROJECT_KEY).getReportAttributes().getVersion()).isEqualTo(expected);
+ }
+
+ private Optional<SnapshotDto> noBaseAnalysisButEnsureIsNotCalled(String projectUuid) {
+ fail("baseAnalysis provider should not have been called");
+ return Optional.absent();
+ }
+
@Test
public void uuid_is_value_from_uuid_supplier_for_project_module_directory_and_file() {
ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(2).build();
}
@Test
- public void createReportAttributes_takes_ref_version_and_path_from_Scanner_Component() {
+ public void createOtherReportAttributes_takes_ref_version_and_path_from_Scanner_Component() {
int ref = 123;
String version = "1.0";
String path = "some path";
- ReportAttributes reportAttributes = createReportAttributes(newBuilder()
+ ReportAttributes reportAttributes = createOtherReportAttributes(newBuilder()
.setRef(ref)
.setVersion(version)
.setPath(path)
}
@Test
- public void createReportAttributes_sets_null_version_when_unset_in_Scanner_Component() {
- ReportAttributes reportAttributes = createReportAttributes(newBuilder().build());
+ public void createOtherReportAttributes_sets_null_version_when_unset_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createOtherReportAttributes(newBuilder().build());
assertThat(reportAttributes.getVersion()).isNull();
}
@Test
- public void createReportAttributes_sets_null_path_when_unset_in_Scanner_Component() {
- ReportAttributes reportAttributes = createReportAttributes(newBuilder().build());
+ public void createOtherReportAttributes_sets_null_version_when_empty_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createOtherReportAttributes(newBuilder().setVersion("").build());
+ assertThat(reportAttributes.getVersion()).isNull();
+ }
+
+ @Test
+ public void createOtherReportAttributes_sets_null_path_when_unset_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createOtherReportAttributes(newBuilder().build());
assertThat(reportAttributes.getPath()).isNull();
}
@Test
- public void createReportAttributes_sets_null_version_when_empty_in_Scanner_Component() {
- ReportAttributes reportAttributes = createReportAttributes(newBuilder().setVersion("").build());
- assertThat(reportAttributes.getVersion()).isNull();
+ public void createOtherReportAttributes_sets_null_path_when_empty_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createOtherReportAttributes(newBuilder().setPath("").build());
+ assertThat(reportAttributes.getPath()).isNull();
+ }
+
+ @Test
+ public void createProjectReportAttributes_sets_null_path_when_unset_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createProjectReportAttributes(newBuilder().build(), PROJECT_UUID, NO_BASEANALYSIS);
+ assertThat(reportAttributes.getPath()).isNull();
}
@Test
- public void createReportAttributes_sets_null_path_when_empty_in_Scanner_Component() {
- ReportAttributes reportAttributes = createReportAttributes(newBuilder().setPath("").build());
+ public void createProjectReportAttributes_sets_null_path_when_empty_in_Scanner_Component() {
+ ReportAttributes reportAttributes = createProjectReportAttributes(newBuilder().setPath("").build(), PROJECT_UUID, NO_BASEANALYSIS);
assertThat(reportAttributes.getPath()).isNull();
}
private static Map<Integer, Component> indexComponentByRef(Component root) {
Map<Integer, Component> componentsByRef = new HashMap<>();
new DepthTraversalTypeAwareCrawler(
- new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, PRE_ORDER) {
- @Override
- public void visitAny(Component any) {
- componentsByRef.put(any.getReportAttributes().getRef(), any);
- }
- }).visit(root);
+ new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, PRE_ORDER) {
+ @Override
+ public void visitAny(Component any) {
+ componentsByRef.put(any.getReportAttributes().getRef(), any);
+ }
+ }).visit(root);
return componentsByRef;
}
}