// 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.objc;

import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.rules.cpp.Link.LINK_LIBRARY_FILETYPES;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.ASSET_CATALOG;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_IMPORT_DIR;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEBUG_SYMBOLS;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEBUG_SYMBOLS_PLIST;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FLAG;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_FOR_XCODEGEN;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_CPP;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.J2OBJC_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKED_BINARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKMAP_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKOPT;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SOURCE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.TOP_LEVEL_MODULE_MAP;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCASSETS_DIR;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XIB;
import static com.google.devtools.build.lib.vfs.PathFragment.TO_PATH_FRAGMENT;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AbstractConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.rules.apple.AppleToolchain;
import com.google.devtools.build.lib.rules.cpp.CcLinkParams;
import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider;
import com.google.devtools.build.lib.rules.cpp.CppCompilationContext;
import com.google.devtools.build.lib.rules.cpp.CppModuleMap;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.PathFragment;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Contains information common to multiple objc_* rules, and provides a unified API for extracting
 * and accessing it.
 */
// TODO(bazel-team): Decompose and subsume area-specific logic and data into the various *Support
// classes. Make sure to distinguish rule output (providers, runfiles, ...) from intermediate,
// rule-internal information. Any provider created by a rule should not be read, only published.
public final class ObjcCommon {
  /**
   * Provides a way to access attributes that are common to all resources rules.
   */
  // TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is
  // gone.
  static final class ResourceAttributes {
    private final RuleContext ruleContext;

    ResourceAttributes(RuleContext ruleContext) {
      this.ruleContext = ruleContext;
    }

    ImmutableList<Artifact> strings() {
      return ruleContext.getPrerequisiteArtifacts("strings", Mode.TARGET).list();
    }

    ImmutableList<Artifact> xibs() {
      return ruleContext.getPrerequisiteArtifacts("xibs", Mode.TARGET).list();
    }

    ImmutableList<Artifact> storyboards() {
      return ruleContext.getPrerequisiteArtifacts("storyboards", Mode.TARGET).list();
    }

    ImmutableList<Artifact> resources() {
      return ruleContext.getPrerequisiteArtifacts("resources", Mode.TARGET).list();
    }

    ImmutableList<Artifact> structuredResources() {
      return ruleContext.getPrerequisiteArtifacts("structured_resources", Mode.TARGET).list();
    }

    ImmutableList<Artifact> datamodels() {
      return ruleContext.getPrerequisiteArtifacts("datamodels", Mode.TARGET).list();
    }

    ImmutableList<Artifact> assetCatalogs() {
      return ruleContext.getPrerequisiteArtifacts("asset_catalogs", Mode.TARGET).list();
    }
  }

  static class Builder {
    private final RuleContext context;
    private final BuildConfiguration buildConfiguration;
    private Optional<CompilationAttributes> compilationAttributes = Optional.absent();
    private Optional<ResourceAttributes> resourceAttributes = Optional.absent();
    private Iterable<SdkFramework> extraSdkFrameworks = ImmutableList.of();
    private Iterable<SdkFramework> extraWeakSdkFrameworks = ImmutableList.of();
    private Iterable<String> extraSdkDylibs = ImmutableList.of();
    private Iterable<Artifact> staticFrameworkImports = ImmutableList.of();
    private Iterable<Artifact> dynamicFrameworkImports = ImmutableList.of();
    private Optional<CompilationArtifacts> compilationArtifacts = Optional.absent();
    private Iterable<ObjcProvider> depObjcProviders = ImmutableList.of();
    private Iterable<ObjcProvider> directDepObjcProviders = ImmutableList.of();
    private Iterable<ObjcProvider> runtimeDepObjcProviders = ImmutableList.of();
    private Iterable<String> defines = ImmutableList.of();
    private Iterable<PathFragment> userHeaderSearchPaths = ImmutableList.of();
    private Iterable<PathFragment> directDependencyHeaderSearchPaths = ImmutableList.of();
    private IntermediateArtifacts intermediateArtifacts;
    private boolean alwayslink;
    private boolean hasModuleMap;
    private Iterable<Artifact> extraImportLibraries = ImmutableList.of();
    private DsymOutputType dsymOutputType;
    private Optional<Artifact> linkedBinary = Optional.absent();
    private Optional<Artifact> linkmapFile = Optional.absent();
    private Iterable<CppCompilationContext> depCcHeaderProviders = ImmutableList.of();
    private Iterable<CcLinkParamsProvider> depCcLinkProviders = ImmutableList.of();

    /**
     * Builder for {@link ObjcCommon} obtaining both attribute data and configuration data from
     * the given rule context.
     */
    Builder(RuleContext context) {
      this(context, context.getConfiguration());
    }

    /**
     * Builder for {@link ObjcCommon} obtaining attribute data from the rule context and
     * configuration data from the given configuration object for use in situations where a single
     * target's outputs are under multiple configurations.
     */
    Builder(RuleContext context, BuildConfiguration buildConfiguration) {
      this.context = Preconditions.checkNotNull(context);
      this.buildConfiguration = Preconditions.checkNotNull(buildConfiguration);
    }

    public Builder setCompilationAttributes(CompilationAttributes baseCompilationAttributes) {
      Preconditions.checkState(
          !this.compilationAttributes.isPresent(),
          "compilationAttributes is already set to: %s",
          this.compilationAttributes);
      this.compilationAttributes = Optional.of(baseCompilationAttributes);
      return this;
    }

    public Builder setResourceAttributes(ResourceAttributes baseResourceAttributes) {
      Preconditions.checkState(
          !this.resourceAttributes.isPresent(),
          "resourceAttributes is already set to: %s",
          this.resourceAttributes);
      this.resourceAttributes = Optional.of(baseResourceAttributes);
      return this;
    }

    Builder addExtraSdkFrameworks(Iterable<SdkFramework> extraSdkFrameworks) {
      this.extraSdkFrameworks = Iterables.concat(this.extraSdkFrameworks, extraSdkFrameworks);
      return this;
    }

    Builder addExtraWeakSdkFrameworks(Iterable<SdkFramework> extraWeakSdkFrameworks) {
      this.extraWeakSdkFrameworks =
          Iterables.concat(this.extraWeakSdkFrameworks, extraWeakSdkFrameworks);
      return this;
    }

    Builder addExtraSdkDylibs(Iterable<String> extraSdkDylibs) {
      this.extraSdkDylibs = Iterables.concat(this.extraSdkDylibs, extraSdkDylibs);
      return this;
    }

    /**
     * Adds all given artifacts as members of static frameworks. They must be contained in
     * {@code .frameworks} directories and the binary in that framework should be statically linked.
     */
    Builder addStaticFrameworkImports(Iterable<Artifact> frameworkImports) {
      this.staticFrameworkImports = Iterables.concat(this.staticFrameworkImports, frameworkImports);
      return this;
    }

    /**
     * Adds all given artifacts as members of dynamic frameworks. They must be contained in
     * {@code .frameworks} directories and the binary in that framework should be dynamically
     * linked.
     */
    Builder addDynamicFrameworkImports(Iterable<Artifact> frameworkImports) {
      this.dynamicFrameworkImports =
          Iterables.concat(this.dynamicFrameworkImports, frameworkImports);
      return this;
    }

    Builder setCompilationArtifacts(CompilationArtifacts compilationArtifacts) {
      Preconditions.checkState(
          !this.compilationArtifacts.isPresent(),
          "compilationArtifacts is already set to: %s",
          this.compilationArtifacts);
      this.compilationArtifacts = Optional.of(compilationArtifacts);
      return this;
    }

    Builder addDeps(List<? extends TransitiveInfoCollection> deps) {
      ImmutableList.Builder<ObjcProvider> propagatedObjcDeps =
          ImmutableList.<ObjcProvider>builder();
      ImmutableList.Builder<CppCompilationContext> cppDeps =
          ImmutableList.<CppCompilationContext>builder();
      ImmutableList.Builder<CcLinkParamsProvider> cppDepLinkParams =
          ImmutableList.<CcLinkParamsProvider>builder();

      for (TransitiveInfoCollection dep : deps) {
        addAnyProviders(propagatedObjcDeps, dep, ObjcProvider.class);
        addAnyProviders(cppDeps, dep, CppCompilationContext.class);
        if (isCcLibrary(dep)) {
          cppDepLinkParams.add(dep.getProvider(CcLinkParamsProvider.class));
          addDefines(dep.getProvider(CppCompilationContext.class).getDefines());
        }
      }
      addDepObjcProviders(propagatedObjcDeps.build());
      this.depCcHeaderProviders = Iterables.concat(this.depCcHeaderProviders, cppDeps.build());
      this.depCcLinkProviders = Iterables.concat(this.depCcLinkProviders, cppDepLinkParams.build());
      return this;
    }

    /**
     * Adds providers for runtime frameworks included in the final app bundle but not linked with
     * at build time.
     */
    Builder addRuntimeDeps(List<? extends TransitiveInfoCollection> runtimeDeps) {
      ImmutableList.Builder<ObjcProvider> propagatedDeps =
          ImmutableList.<ObjcProvider>builder();

      for (TransitiveInfoCollection dep : runtimeDeps) {
        addAnyProviders(propagatedDeps, dep, ObjcProvider.class);
      }
      this.runtimeDepObjcProviders = Iterables.concat(
          this.runtimeDepObjcProviders, propagatedDeps.build());
      return this;
    }

    private <T extends TransitiveInfoProvider> ImmutableList.Builder<T> addAnyProviders(
        ImmutableList.Builder<T> listBuilder,
        TransitiveInfoCollection collection,
        Class<T> providerClass) {
      if (collection.getProvider(providerClass) != null) {
        listBuilder.add(collection.getProvider(providerClass));
      }
      return listBuilder;
    }

    /**
     * Add providers which will be exposed both to the declaring rule and to any dependers on the
     * declaring rule.
     */
    Builder addDepObjcProviders(Iterable<ObjcProvider> depObjcProviders) {
      this.depObjcProviders = Iterables.concat(this.depObjcProviders, depObjcProviders);
      return this;
    }

    /**
     * Add providers which will only be used by the declaring rule, and won't be propagated to any
     * dependers on the declaring rule.
     */
    Builder addNonPropagatedDepObjcProviders(Iterable<ObjcProvider> directDepObjcProviders) {
      this.directDepObjcProviders =
          Iterables.concat(this.directDepObjcProviders, directDepObjcProviders);
      return this;
    }

    public Builder addUserHeaderSearchPaths(Iterable<PathFragment> userHeaderSearchPaths) {
      this.userHeaderSearchPaths =
          Iterables.concat(this.userHeaderSearchPaths, userHeaderSearchPaths);
      return this;
    }

    /**
     * Adds header search paths that will only be visible by strict dependents of the provider.
     */
    public Builder addDirectDependencyHeaderSearchPaths(
        Iterable<PathFragment> directDependencyHeaderSearchPaths) {
      this.directDependencyHeaderSearchPaths =
          Iterables.concat(
              this.directDependencyHeaderSearchPaths, directDependencyHeaderSearchPaths);
      return this;
    }

    public Builder addDefines(Iterable<String> defines) {
      this.defines = Iterables.concat(this.defines, defines);
      return this;
    }

    Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
      this.intermediateArtifacts = intermediateArtifacts;
      return this;
    }

    Builder setAlwayslink(boolean alwayslink) {
      this.alwayslink = alwayslink;
      return this;
    }

    /**
     * Specifies that this target has a clang module map. This should be called if this target
     * compiles sources or exposes headers for other targets to use. Note that this does not add
     * the action to generate the module map. It simply indicates that it should be added to the
     * provider.
     */
    Builder setHasModuleMap() {
      this.hasModuleMap = true;
      return this;
    }

    /**
     * Adds additional static libraries to be linked into the final ObjC application bundle.
     */
    Builder addExtraImportLibraries(Iterable<Artifact> extraImportLibraries) {
      this.extraImportLibraries = Iterables.concat(this.extraImportLibraries, extraImportLibraries);
      return this;
    }

    /**
     * Sets a linked binary generated by this rule to be propagated to dependers.
     */
    Builder setLinkedBinary(Artifact linkedBinary) {
      this.linkedBinary = Optional.of(linkedBinary);
      return this;
    }

    /**
     * Sets which type of dsym output this rule generated to be propagated to dependers.
     */
    Builder addDebugArtifacts(DsymOutputType dsymOutputType) {
      this.dsymOutputType = dsymOutputType;
      return this;
    }

    /**
     * Sets a linkmap file generated by this rule to be propagated to dependers.
     */
    Builder setLinkmapFile(Artifact linkmapFile) {
      this.linkmapFile = Optional.of(linkmapFile);
      return this;
    }

    ObjcCommon build() {
      Iterable<BundleableFile> bundleImports = BundleableFile.bundleImportsFromRule(context);

      ObjcProvider.Builder objcProvider =
          new ObjcProvider.Builder()
              .addAll(IMPORTED_LIBRARY, extraImportLibraries)
              .addAll(BUNDLE_FILE, bundleImports)
              .addAll(
                  BUNDLE_IMPORT_DIR,
                  uniqueContainers(
                      BundleableFile.toArtifacts(bundleImports), BUNDLE_CONTAINER_TYPE))
              .addAll(SDK_FRAMEWORK, extraSdkFrameworks)
              .addAll(WEAK_SDK_FRAMEWORK, extraWeakSdkFrameworks)
              .addAll(SDK_DYLIB, extraSdkDylibs)
              .addAll(STATIC_FRAMEWORK_FILE, staticFrameworkImports)
              .addAll(DYNAMIC_FRAMEWORK_FILE, dynamicFrameworkImports)
              .addAll(
                  FRAMEWORK_DIR, uniqueContainers(staticFrameworkImports, FRAMEWORK_CONTAINER_TYPE))
              .addAll(
                  FRAMEWORK_DIR,
                  uniqueContainers(dynamicFrameworkImports, FRAMEWORK_CONTAINER_TYPE))
              .addAll(INCLUDE, userHeaderSearchPaths)
              .addAllForDirectDependents(INCLUDE, directDependencyHeaderSearchPaths)
              .addAll(DEFINE, defines)
              .addTransitiveAndPropagate(depObjcProviders)
              .addTransitiveWithoutPropagating(directDepObjcProviders);

      for (ObjcProvider provider : runtimeDepObjcProviders) {
        objcProvider.addTransitiveAndPropagate(ObjcProvider.DYNAMIC_FRAMEWORK_FILE, provider);
        // TODO(b/28637288): Remove STATIC_FRAMEWORK_FILE and MERGE_ZIP when they are
        // no longer provided by ios_framework.
        objcProvider.addTransitiveAndPropagate(ObjcProvider.STATIC_FRAMEWORK_FILE, provider);
        objcProvider.addTransitiveAndPropagate(ObjcProvider.MERGE_ZIP, provider);
      }

      for (CppCompilationContext headerProvider : depCcHeaderProviders) {
        objcProvider.addTransitiveAndPropagate(HEADER, headerProvider.getDeclaredIncludeSrcs());
        objcProvider.addAll(INCLUDE, headerProvider.getIncludeDirs());
        // TODO(bazel-team): This pulls in stl via CppHelper.mergeToolchainDependentContext but
        // probably shouldn't.
        objcProvider.addAll(INCLUDE_SYSTEM, headerProvider.getSystemIncludeDirs());
        objcProvider.addAll(DEFINE, headerProvider.getDefines());
      }
      for (CcLinkParamsProvider linkProvider : depCcLinkProviders) {
        CcLinkParams params = linkProvider.getCcLinkParams(true, false);
        ImmutableList<String> linkOpts = params.flattenedLinkopts();
        ImmutableSet.Builder<SdkFramework> frameworkLinkOpts = new ImmutableSet.Builder<>();
        ImmutableList.Builder<String> nonFrameworkLinkOpts = new ImmutableList.Builder<>();
        // Add any framework flags as frameworks directly, rather than as linkopts.
        for (UnmodifiableIterator<String> iterator = linkOpts.iterator(); iterator.hasNext(); ) {
          String arg = iterator.next();
          if (arg.equals("-framework") && iterator.hasNext()) {
            String framework = iterator.next();
            frameworkLinkOpts.add(new SdkFramework(framework));
          } else {
            nonFrameworkLinkOpts.add(arg);
          }
        }

        objcProvider
            .addAll(SDK_FRAMEWORK, frameworkLinkOpts.build())
            .addAll(LINKOPT, nonFrameworkLinkOpts.build())
            .addTransitiveAndPropagate(CC_LIBRARY, params.getLibraries());

        for (LinkerInputs.LibraryToLink library : params.getLibraries()) {
          Artifact artifact = library.getArtifact();
          if (LINK_LIBRARY_FILETYPES.matches(artifact.getFilename())) {
            objcProvider.add(
                FORCE_LOAD_FOR_XCODEGEN,
                "$(WORKSPACE_ROOT)/" + artifact.getExecPath().getSafePathString());
          }
        }
      }

      if (compilationAttributes.isPresent()) {
        CompilationAttributes attributes = compilationAttributes.get();
        Iterable<PathFragment> sdkIncludes =
            Iterables.transform(
                Interspersing.prependEach(
                    AppleToolchain.sdkDir() + "/usr/include/",
                    PathFragment.safePathStrings(attributes.sdkIncludes())),
                TO_PATH_FRAGMENT);
        objcProvider
            .addAll(HEADER, attributes.hdrs())
            .addAll(HEADER, attributes.textualHdrs())
            .addAll(INCLUDE, attributes.headerSearchPaths(buildConfiguration.getGenfilesFragment()))
            .addAll(INCLUDE, sdkIncludes)
            .addAll(SDK_FRAMEWORK, attributes.sdkFrameworks())
            .addAll(WEAK_SDK_FRAMEWORK, attributes.weakSdkFrameworks())
            .addAll(SDK_DYLIB, attributes.sdkDylibs());
      }

      if (resourceAttributes.isPresent()) {
        ResourceAttributes attributes = resourceAttributes.get();
        objcProvider
            .addAll(GENERAL_RESOURCE_FILE, attributes.storyboards())
            .addAll(GENERAL_RESOURCE_FILE, attributes.resources())
            .addAll(GENERAL_RESOURCE_FILE, attributes.strings())
            .addAll(GENERAL_RESOURCE_FILE, attributes.xibs())
            .addAll(
                GENERAL_RESOURCE_DIR, xcodeStructuredResourceDirs(attributes.structuredResources()))
            .addAll(BUNDLE_FILE, BundleableFile.flattenedRawResourceFiles(attributes.resources()))
            .addAll(
                BUNDLE_FILE,
                BundleableFile.structuredRawResourceFiles(attributes.structuredResources()))
            .addAll(
                XCASSETS_DIR,
                uniqueContainers(attributes.assetCatalogs(), ASSET_CATALOG_CONTAINER_TYPE))
            .addAll(ASSET_CATALOG, attributes.assetCatalogs())
            .addAll(XCDATAMODEL, attributes.datamodels())
            .addAll(XIB, attributes.xibs())
            .addAll(STRINGS, attributes.strings())
            .addAll(STORYBOARD, attributes.storyboards());
      }

      if (useLaunchStoryboard(context)) {
        Artifact launchStoryboard =
            context.getPrerequisiteArtifact("launch_storyboard", Mode.TARGET);
        objcProvider.add(GENERAL_RESOURCE_FILE, launchStoryboard);
        if (ObjcRuleClasses.STORYBOARD_TYPE.matches(launchStoryboard.getPath())) {
          objcProvider.add(STORYBOARD, launchStoryboard);
        } else {
          objcProvider.add(XIB, launchStoryboard);
        }
      }

      for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) {
        Iterable<Artifact> allSources =
            Iterables.concat(artifacts.getSrcs(), artifacts.getNonArcSrcs());
        // TODO(bazel-team): Add private headers to the provider when we have module maps to enforce
        // them.
        objcProvider
            .addAll(HEADER, artifacts.getAdditionalHdrs())
            .addAll(LIBRARY, artifacts.getArchive().asSet())
            .addAll(SOURCE, allSources);

        if (artifacts.getArchive().isPresent()
            && J2ObjcLibrary.J2OBJC_SUPPORTED_RULES.contains(context.getRule().getRuleClass())) {
          objcProvider.addAll(J2OBJC_LIBRARY, artifacts.getArchive().asSet());
        }

        boolean usesCpp = false;
        boolean usesSwift = false;
        for (Artifact sourceFile :
            Iterables.concat(artifacts.getSrcs(), artifacts.getNonArcSrcs())) {
          usesCpp = usesCpp || ObjcRuleClasses.CPP_SOURCES.matches(sourceFile.getExecPath());
          usesSwift = usesSwift || ObjcRuleClasses.SWIFT_SOURCES.matches(sourceFile.getExecPath());
        }

        if (usesCpp) {
          objcProvider.add(FLAG, USES_CPP);
        }

        if (usesSwift) {
          objcProvider.add(FLAG, USES_SWIFT);
        }
      }

      if (alwayslink) {
        for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) {
          for (Artifact archive : artifacts.getArchive().asSet()) {
            objcProvider.add(FORCE_LOAD_LIBRARY, archive);
            objcProvider.add(
                FORCE_LOAD_FOR_XCODEGEN,
                String.format(
                    "$(BUILT_PRODUCTS_DIR)/lib%s.a",
                    XcodeProvider.xcodeTargetName(context.getLabel())));
          }
        }
        for (Artifact archive : extraImportLibraries) {
          objcProvider.add(FORCE_LOAD_LIBRARY, archive);
          objcProvider.add(
              FORCE_LOAD_FOR_XCODEGEN,
              "$(WORKSPACE_ROOT)/" + archive.getExecPath().getSafePathString());
        }
      }

      if (hasModuleMap) {
        CppModuleMap moduleMap = intermediateArtifacts.moduleMap();
        objcProvider.add(MODULE_MAP, moduleMap.getArtifact());
        objcProvider.add(TOP_LEVEL_MODULE_MAP, moduleMap);
      }

      objcProvider
          .addAll(LINKED_BINARY, linkedBinary.asSet())
          .addAll(LINKMAP_FILE, linkmapFile.asSet());

      if (dsymOutputType != null) {
        objcProvider
            .add(DEBUG_SYMBOLS, intermediateArtifacts.dsymSymbol(dsymOutputType))
            .add(DEBUG_SYMBOLS_PLIST, intermediateArtifacts.dsymPlist(dsymOutputType));
      }

      return new ObjcCommon(objcProvider.build(), compilationArtifacts);
    }

    private static boolean isCcLibrary(TransitiveInfoCollection info) {
      try {
        AbstractConfiguredTarget target = (AbstractConfiguredTarget) info;
        String targetName = target.getTarget().getTargetKind();
        for (String ruleClassName : ObjcRuleClasses.CompilingRule.ALLOWED_CC_DEPS_RULE_CLASSES) {
          if (targetName.equals(ruleClassName + " rule")) {
            return true;
          }
        }
        return false;
      } catch (Exception e) {
        return false;
      }
    }
    
    /**
     * Returns {@code true} if the given rule context has a launch storyboard set.
     */
    private static boolean useLaunchStoryboard(RuleContext ruleContext) {
      if (!ruleContext.attributes().has("launch_storyboard", LABEL)) {
        return false;
      }
      Artifact launchStoryboard =
          ruleContext.getPrerequisiteArtifact("launch_storyboard", Mode.TARGET);
      return launchStoryboard != null;
    }
  }

  static final FileType BUNDLE_CONTAINER_TYPE = FileType.of(".bundle");

  static final FileType ASSET_CATALOG_CONTAINER_TYPE = FileType.of(".xcassets");

  public static final FileType FRAMEWORK_CONTAINER_TYPE = FileType.of(".framework");
  private final ObjcProvider objcProvider;

  private final Optional<CompilationArtifacts> compilationArtifacts;

  private ObjcCommon(
      ObjcProvider objcProvider, Optional<CompilationArtifacts> compilationArtifacts) {
    this.objcProvider = Preconditions.checkNotNull(objcProvider);
    this.compilationArtifacts = Preconditions.checkNotNull(compilationArtifacts);
  }

  public ObjcProvider getObjcProvider() {
    return objcProvider;
  }

  public Optional<CompilationArtifacts> getCompilationArtifacts() {
    return compilationArtifacts;
  }

  /**
   * Returns an {@link Optional} containing the compiled {@code .a} file, or
   * {@link Optional#absent()} if this object contains no {@link CompilationArtifacts} or the
   * compilation information has no sources.
   */
  public Optional<Artifact> getCompiledArchive() {
    if (compilationArtifacts.isPresent()) {
      return compilationArtifacts.get().getArchive();
    }
    return Optional.absent();
  }

  /**
   * Returns effective compilation options that do not arise from the crosstool.
   */
  static Iterable<String> getNonCrosstoolCopts(RuleContext ruleContext) {
    return Iterables.concat(
        ruleContext.getFragment(ObjcConfiguration.class).getCopts(),
        ruleContext.getTokenizedStringListAttr("copts"));
  }

  static boolean shouldUseObjcModules(RuleContext ruleContext) {
    for (String copt : getNonCrosstoolCopts(ruleContext)) {
      if (copt.contains("-fmodules")) {
        return true;
      }
    }

    if (ruleContext.attributes().has("enable_modules", Type.BOOLEAN)
        && ruleContext.attributes().get("enable_modules", Type.BOOLEAN)) {
      return true;
    }

    if (ruleContext.getFragment(ObjcConfiguration.class).moduleMapsEnabled()) {
      return true;
    }

    return false;
  }

  static ImmutableList<PathFragment> userHeaderSearchPaths(BuildConfiguration configuration) {
    return ImmutableList.of(new PathFragment("."), configuration.getGenfilesFragment());
  }

  /**
   * Returns the first directory in the sequence of parents of the exec path of the given artifact
   * that matches {@code type}. For instance, if {@code type} is FileType.of(".foo") and the exec
   * path of {@code artifact} is {@code a/b/c/bar.foo/d/e}, then the return value is
   * {@code a/b/c/bar.foo}.
   */
  static Optional<PathFragment> nearestContainerMatching(FileType type, Artifact artifact) {
    PathFragment container = artifact.getExecPath();
    do {
      if (type.matches(container)) {
        return Optional.of(container);
      }
      container = container.getParentDirectory();
    } while (container != null);
    return Optional.absent();
  }

  /**
   * Similar to {@link #nearestContainerMatching(FileType, Artifact)}, but tries matching several
   * file types in {@code types}, and returns a path for the first match in the sequence.
   */
  static Optional<PathFragment> nearestContainerMatching(
      Iterable<FileType> types, Artifact artifact) {
    for (FileType type : types) {
      for (PathFragment container : nearestContainerMatching(type, artifact).asSet()) {
        return Optional.of(container);
      }
    }
    return Optional.absent();
  }

  /**
   * Returns all directories matching {@code containerType} that contain the items in
   * {@code artifacts}. This function ignores artifacts that are not in any directory matching
   * {@code containerType}.
   */
  static Iterable<PathFragment> uniqueContainers(
      Iterable<Artifact> artifacts, FileType containerType) {
    ImmutableSet.Builder<PathFragment> containers = new ImmutableSet.Builder<>();
    for (Artifact artifact : artifacts) {
      containers.addAll(ObjcCommon.nearestContainerMatching(containerType, artifact).asSet());
    }
    return containers.build();
  }

  /**
   * Returns the Xcode structured resource directory paths.
   *
   * <p>For a checked-in source artifact "//a/b/res/sub_dir/d" included by objc rule "//a/b:c",
   * "a/b/res" will be returned. For a generated source artifact "res/sub_dir/d" owned by genrule
   * "//a/b:c", "bazel-out/.../genfiles/a/b/res" will be returned.
   *
   * <p>When XCode sees a included resource directory of "a/b/res", the entire directory structure
   * up to "res" will be copied into the app bundle.
   */
  static Iterable<PathFragment> xcodeStructuredResourceDirs(Iterable<Artifact> artifacts) {
    ImmutableSet.Builder<PathFragment> containers = new ImmutableSet.Builder<>();
    for (Artifact artifact : artifacts) {
      PathFragment ownerRuleDirectory = artifact.getArtifactOwner().getLabel().getPackageFragment();
      String containerName =
          artifact.getRootRelativePath().relativeTo(ownerRuleDirectory).getSegment(0);
      PathFragment rootExecPath = artifact.getRoot().getExecPath();
      containers.add(rootExecPath.getRelative(ownerRuleDirectory.getRelative(containerName)));
    }

    return containers.build();
  }

  /**
   * Similar to {@link #nearestContainerMatching(FileType, Artifact)}, but returns the container
   * closest to the root that matches the given type.
   */
  static Optional<PathFragment> farthestContainerMatching(FileType type, Artifact artifact) {
    PathFragment container = artifact.getExecPath();
    Optional<PathFragment> lastMatch = Optional.absent();
    do {
      if (type.matches(container)) {
        lastMatch = Optional.of(container);
      }
      container = container.getParentDirectory();
    } while (container != null);
    return lastMatch;
  }

  static Iterable<String> notInContainerErrors(
      Iterable<Artifact> artifacts, FileType containerType) {
    return notInContainerErrors(artifacts, ImmutableList.of(containerType));
  }

  @VisibleForTesting
  static final String NOT_IN_CONTAINER_ERROR_FORMAT =
      "File '%s' is not in a directory of one of these type(s): %s";

  static Iterable<String> notInContainerErrors(
      Iterable<Artifact> artifacts, Iterable<FileType> containerTypes) {
    Set<String> errors = new HashSet<>();
    for (Artifact artifact : artifacts) {
      boolean inContainer = nearestContainerMatching(containerTypes, artifact).isPresent();
      if (!inContainer) {
        errors.add(
            String.format(
                NOT_IN_CONTAINER_ERROR_FORMAT,
                artifact.getExecPath(),
                Iterables.toString(containerTypes)));
      }
    }
    return errors;
  }
}
