<commit_before>// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.rules.cpp;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.cpp.IncludeScanner.IncludeScanningHeaderData;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcCompilationContextApi;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Immutable store of information needed for C++ compilation that is aggregated across dependencies.
 */
@Immutable
@AutoCodec
// TODO(b/77669139): Rename to CcCompilationContext.
public final class CcCompilationContext implements CcCompilationContextApi {
  /** An empty {@code CcCompilationContext}. */
  public static final CcCompilationContext EMPTY = new Builder(null).build();

  private final CommandLineCcCompilationContext commandLineCcCompilationContext;

  private final NestedSet<PathFragment> declaredIncludeDirs;
  private final NestedSet<Artifact> declaredIncludeSrcs;

  /** Module maps from direct dependencies. */
  private final ImmutableList<Artifact> directModuleMaps;

  /** Non-code mandatory compilation inputs. */
  private final NestedSet<Artifact> nonCodeInputs;

  private final HeaderInfo headerInfo;
  private final NestedSet<HeaderInfo> transitiveHeaderInfos;
  private final NestedSet<Artifact> transitiveModules;
  private final NestedSet<Artifact> transitivePicModules;

  private final CppModuleMap cppModuleMap;
  private final CppModuleMap verificationModuleMap;

  private final boolean propagateModuleMapAsActionInput;

  // Derived from depsContexts.
  private final ImmutableSet<Artifact> compilationPrerequisites;

  private final CppConfiguration.HeadersCheckingMode headersCheckingMode;

  // Each pair maps the Bazel generated paths of virtual include headers back to their original path
  // relative to the workspace directory.
  // For example it can map
  // "bazel-out/k8-fastbuild/bin/include/common/_virtual_includes/strategy/strategy.h"
  // back to the path of the header in the workspace directory "include/common/strategy.h".
  // This is needed only when code coverage collection is enabled, to report the actual source file
  // name in the coverage output file.
  private final NestedSet<Pair<String, String>> virtualToOriginalHeaders;

  @AutoCodec.Instantiator
  @VisibleForSerialization
  CcCompilationContext(
      CommandLineCcCompilationContext commandLineCcCompilationContext,
      ImmutableSet<Artifact> compilationPrerequisites,
      NestedSet<PathFragment> declaredIncludeDirs,
      NestedSet<Artifact> declaredIncludeSrcs,
      NestedSet<Artifact> nonCodeInputs,
      HeaderInfo headerInfo,
      NestedSet<HeaderInfo> transitiveHeaderInfos,
      NestedSet<Artifact> transitiveModules,
      NestedSet<Artifact> transitivePicModules,
      ImmutableList<Artifact> directModuleMaps,
      CppModuleMap cppModuleMap,
      @Nullable CppModuleMap verificationModuleMap,
      boolean propagateModuleMapAsActionInput,
      CppConfiguration.HeadersCheckingMode headersCheckingMode,
      NestedSet<Pair<String, String>> virtualToOriginalHeaders) {
    Preconditions.checkNotNull(commandLineCcCompilationContext);
    this.commandLineCcCompilationContext = commandLineCcCompilationContext;
    this.declaredIncludeDirs = declaredIncludeDirs;
    this.declaredIncludeSrcs = declaredIncludeSrcs;
    this.directModuleMaps = directModuleMaps;
    this.headerInfo = headerInfo;
    this.transitiveHeaderInfos = transitiveHeaderInfos;
    this.transitiveModules = transitiveModules;
    this.transitivePicModules = transitivePicModules;
    this.cppModuleMap = cppModuleMap;
    this.nonCodeInputs = nonCodeInputs;
    this.verificationModuleMap = verificationModuleMap;
    this.compilationPrerequisites = compilationPrerequisites;
    this.propagateModuleMapAsActionInput = propagateModuleMapAsActionInput;
    this.headersCheckingMode = headersCheckingMode;
    this.virtualToOriginalHeaders = virtualToOriginalHeaders;
  }

  @Override
  public SkylarkNestedSet getSkylarkDefines() {
    return SkylarkNestedSet.of(
        String.class, NestedSetBuilder.wrap(Order.STABLE_ORDER, getDefines()));
  }

  @Override
  public SkylarkNestedSet getSkylarkHeaders() {
    return SkylarkNestedSet.of(Artifact.class, getDeclaredIncludeSrcs());
  }

  @Override
  public SkylarkNestedSet getSkylarkSystemIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getSystemIncludeDirs().stream()
                .map(PathFragment::getPathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public SkylarkNestedSet getSkylarkIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getIncludeDirs().stream()
                .map(PathFragment::getPathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public SkylarkNestedSet getSkylarkQuoteIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getQuoteIncludeDirs().stream()
                .map(PathFragment::getPathString)
                .collect(ImmutableList.toImmutableList())));
  }

  /**
   * Returns the transitive compilation prerequisites consolidated into middlemen prerequisites, or
   * an empty set if there are no prerequisites.
   *
   * <p>Transitive compilation prerequisites are the prerequisites that will be needed by all
   * reverse dependencies; note that these do specifically not include any compilation prerequisites
   * that are only needed by the rule itself (for example, compiled source files from the {@code
   * srcs} attribute).
   *
   * <p>To reduce the number of edges in the action graph, we express the dependency on compilation
   * prerequisites as a transitive dependency via a middleman. After they have been accumulated
   * ({@link Builder#mergeDependentCcCompilationContext(CcCompilationContext)}, and {@link
   * Builder#mergeDependentCcCompilationContexts(Iterable)}, they are consolidated into a single
   * middleman Artifact when {@link Builder#build()} is called.
   *
   * <p>The returned set can be empty if there are no prerequisites. Usually, it contains a single
   * middleman.
   */
  public ImmutableSet<Artifact> getTransitiveCompilationPrerequisites() {
    return compilationPrerequisites;
  }<commit_msg>C++: Return getSafePathString instead of getPathString<commit_after>// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.rules.cpp;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.cpp.IncludeScanner.IncludeScanningHeaderData;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcCompilationContextApi;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Immutable store of information needed for C++ compilation that is aggregated across dependencies.
 */
@Immutable
@AutoCodec
// TODO(b/77669139): Rename to CcCompilationContext.
public final class CcCompilationContext implements CcCompilationContextApi {
  /** An empty {@code CcCompilationContext}. */
  public static final CcCompilationContext EMPTY = new Builder(null).build();

  private final CommandLineCcCompilationContext commandLineCcCompilationContext;

  private final NestedSet<PathFragment> declaredIncludeDirs;
  private final NestedSet<Artifact> declaredIncludeSrcs;

  /** Module maps from direct dependencies. */
  private final ImmutableList<Artifact> directModuleMaps;

  /** Non-code mandatory compilation inputs. */
  private final NestedSet<Artifact> nonCodeInputs;

  private final HeaderInfo headerInfo;
  private final NestedSet<HeaderInfo> transitiveHeaderInfos;
  private final NestedSet<Artifact> transitiveModules;
  private final NestedSet<Artifact> transitivePicModules;

  private final CppModuleMap cppModuleMap;
  private final CppModuleMap verificationModuleMap;

  private final boolean propagateModuleMapAsActionInput;

  // Derived from depsContexts.
  private final ImmutableSet<Artifact> compilationPrerequisites;

  private final CppConfiguration.HeadersCheckingMode headersCheckingMode;

  // Each pair maps the Bazel generated paths of virtual include headers back to their original path
  // relative to the workspace directory.
  // For example it can map
  // "bazel-out/k8-fastbuild/bin/include/common/_virtual_includes/strategy/strategy.h"
  // back to the path of the header in the workspace directory "include/common/strategy.h".
  // This is needed only when code coverage collection is enabled, to report the actual source file
  // name in the coverage output file.
  private final NestedSet<Pair<String, String>> virtualToOriginalHeaders;

  @AutoCodec.Instantiator
  @VisibleForSerialization
  CcCompilationContext(
      CommandLineCcCompilationContext commandLineCcCompilationContext,
      ImmutableSet<Artifact> compilationPrerequisites,
      NestedSet<PathFragment> declaredIncludeDirs,
      NestedSet<Artifact> declaredIncludeSrcs,
      NestedSet<Artifact> nonCodeInputs,
      HeaderInfo headerInfo,
      NestedSet<HeaderInfo> transitiveHeaderInfos,
      NestedSet<Artifact> transitiveModules,
      NestedSet<Artifact> transitivePicModules,
      ImmutableList<Artifact> directModuleMaps,
      CppModuleMap cppModuleMap,
      @Nullable CppModuleMap verificationModuleMap,
      boolean propagateModuleMapAsActionInput,
      CppConfiguration.HeadersCheckingMode headersCheckingMode,
      NestedSet<Pair<String, String>> virtualToOriginalHeaders) {
    Preconditions.checkNotNull(commandLineCcCompilationContext);
    this.commandLineCcCompilationContext = commandLineCcCompilationContext;
    this.declaredIncludeDirs = declaredIncludeDirs;
    this.declaredIncludeSrcs = declaredIncludeSrcs;
    this.directModuleMaps = directModuleMaps;
    this.headerInfo = headerInfo;
    this.transitiveHeaderInfos = transitiveHeaderInfos;
    this.transitiveModules = transitiveModules;
    this.transitivePicModules = transitivePicModules;
    this.cppModuleMap = cppModuleMap;
    this.nonCodeInputs = nonCodeInputs;
    this.verificationModuleMap = verificationModuleMap;
    this.compilationPrerequisites = compilationPrerequisites;
    this.propagateModuleMapAsActionInput = propagateModuleMapAsActionInput;
    this.headersCheckingMode = headersCheckingMode;
    this.virtualToOriginalHeaders = virtualToOriginalHeaders;
  }

  @Override
  public SkylarkNestedSet getSkylarkDefines() {
    return SkylarkNestedSet.of(
        String.class, NestedSetBuilder.wrap(Order.STABLE_ORDER, getDefines()));
  }

  @Override
  public SkylarkNestedSet getSkylarkHeaders() {
    return SkylarkNestedSet.of(Artifact.class, getDeclaredIncludeSrcs());
  }

  @Override
  public SkylarkNestedSet getSkylarkSystemIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getSystemIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public SkylarkNestedSet getSkylarkIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public SkylarkNestedSet getSkylarkQuoteIncludeDirs() {
    return SkylarkNestedSet.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getQuoteIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  /**
   * Returns the transitive compilation prerequisites consolidated into middlemen prerequisites, or
   * an empty set if there are no prerequisites.
   *
   * <p>Transitive compilation prerequisites are the prerequisites that will be needed by all
   * reverse dependencies; note that these do specifically not include any compilation prerequisites
   * that are only needed by the rule itself (for example, compiled source files from the {@code
   * srcs} attribute).
   *
   * <p>To reduce the number of edges in the action graph, we express the dependency on compilation
   * prerequisites as a transitive dependency via a middleman. After they have been accumulated
   * ({@link Builder#mergeDependentCcCompilationContext(CcCompilationContext)}, and {@link
   * Builder#mergeDependentCcCompilationContexts(Iterable)}, they are consolidated into a single
   * middleman Artifact when {@link Builder#build()} is called.
   *
   * <p>The returned set can be empty if there are no prerequisites. Usually, it contains a single
   * middleman.
   */
  public ImmutableSet<Artifact> getTransitiveCompilationPrerequisites() {
    return compilationPrerequisites;
  }
{'fraction_non_alphanumeric': 0.07776923531846945, 'fraction_numerical': 0.002010763498728488, 'mean_word_length': 4.537000654878847, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6723572', 'n_tokens_mistral': 4782, 'n_tokens_neox': 4672, 'n_words': 1137}