All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.j2cl.transpiler.frontend.jdt.PackageAnnotationsResolver Maven / Gradle / Ivy

There is a newer version: v20241110-1
Show newest version
/*
 * Copyright 2023 Google Inc.
 *
 * 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.j2cl.transpiler.frontend.jdt;

import static com.google.common.base.Preconditions.checkState;
import static com.google.j2cl.transpiler.frontend.common.PackageInfoCache.DEFAULT_PACKAGE_REPORT;
import static com.google.j2cl.transpiler.frontend.jdt.JsInteropAnnotationUtils.getJsNamespace;
import static com.google.j2cl.transpiler.frontend.jdt.KtInteropAnnotationUtils.getKtObjectiveCName;
import static java.util.Arrays.stream;

import com.google.common.collect.ImmutableList;
import com.google.j2cl.common.SourceUtils.FileInfo;
import com.google.j2cl.transpiler.frontend.common.Nullability;
import com.google.j2cl.transpiler.frontend.common.PackageInfoCache.PackageReport;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;

/** A utility class to resolve and cache package annotations. */
public final class PackageAnnotationsResolver {

  private final Map packageReportByPackageName = new HashMap<>();
  private final JdtParser parser;

  /** Create a PackageAnnotationResolver with the source package-info CompilationUnits. */
  public static PackageAnnotationsResolver create(
      Stream packageInfoCompilationUnits, JdtParser parser) {
    var packageAnnotationResolver = new PackageAnnotationsResolver(parser);
    packageAnnotationResolver.populateFromCompilationUnits(packageInfoCompilationUnits);
    return packageAnnotationResolver;
  }

  /** Create a PackageAnnotationResolver with package infos in sources. */
  public static PackageAnnotationsResolver create(List sources, JdtParser parser) {
    return create(parsePackageInfoFiles(sources, parser), parser);
  }

  public String getJsNameSpace(String packageName) {
    return getPackageReport(packageName).getJsNamespace();
  }

  public String getObjectiveCNamePrefix(String packageName) {
    return getPackageReport(packageName).getObjectiveCName();
  }

  public boolean isNullMarked(String packageName) {
    return getPackageReport(packageName).isNullMarked();
  }

  /** Parser package-info files from sources. */
  private static Stream parsePackageInfoFiles(
      List sources, JdtParser parser) {

    if (sources.isEmpty()) {
      return Stream.of();
    }

    var parsingResult = parser.parseFiles(sources, false, ImmutableList.of());
    return parsingResult.getCompilationUnitsByFilePath().values().stream();
  }

  /** Populates the cache for the annotations in package-info compilation units. */
  private void populateFromCompilationUnits(Stream packageInfoCompilationUnits) {
    packageInfoCompilationUnits.forEach(
        cu -> {
          var packageDeclaration = cu.getPackage();

          // Sanity check, package-info.java files declare no types.
          checkState(cu.types().isEmpty());

          // Records information about package-info files supplied as source code.
          if (packageDeclaration != null) {
            setPackageProperties(
                packageDeclaration.getName().getFullyQualifiedName(),
                getJsNamespace(packageDeclaration),
                getKtObjectiveCName(packageDeclaration),
                JdtAnnotationUtils.isNullMarked(packageDeclaration));
          }
        });
  }

  public void setPackageProperties(
      String packageName, String jsNamespace, String objectiveCName, boolean isNullMarked) {
    packageReportByPackageName.put(
        packageName,
        PackageReport.newBuilder()
            .setJsNamespace(jsNamespace)
            .setObjectiveCName(objectiveCName)
            .setNullMarked(isNullMarked)
            .build());
  }

  private PackageReport getPackageReport(String packageName) {
    return packageReportByPackageName.computeIfAbsent(packageName, this::createPackageReport);
  }

  private PackageReport createPackageReport(String packageName) {
    ITypeBinding packageInfoBinding = parser.resolveBinding(packageName + ".package-info");
    if (packageInfoBinding == null) {
      return DEFAULT_PACKAGE_REPORT;
    }

    boolean isNullMarked =
        stream(packageInfoBinding.getAnnotations())
            .anyMatch(
                a -> Nullability.isNullMarkedAnnotation(a.getAnnotationType().getQualifiedName()));

    String objectiveCName =
        getKtObjectiveCName(
            KtInteropAnnotationUtils.getKtObjectiveCNameAnnotation(
                packageInfoBinding.getAnnotations()));

    String jsNamespace =
        getJsNamespace(JsInteropAnnotationUtils.getJsPackageAnnotation(packageInfoBinding));
    return PackageReport.newBuilder()
        .setJsNamespace(jsNamespace)
        .setObjectiveCName(objectiveCName)
        .setNullMarked(isNullMarked)
        .build();
  }

  private PackageAnnotationsResolver(JdtParser parser) {
    this.parser = parser;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy