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

org.pkl.core.PClass Maven / Gradle / Ivy

Go to download

Shaded fat Jar for pkl-config-java, a Java config library based on the Pkl config language.

There is a newer version: 0.27.1
Show newest version
/*
 * Copyright © 2024 Apple Inc. and the Pkl project 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
 *
 *     https://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 org.pkl.core;

import java.io.Serial;
import java.util.*;
import org.pkl.core.util.Nullable;

/** Java representation of a {@code pkl.base#Class} value. */
public final class PClass extends Member implements Value {
  @Serial private static final long serialVersionUID = 0L;

  private final PClassInfo classInfo;
  private final List typeParameters;
  private final Map properties;
  private final Map methods;

  private @Nullable PType supertype;
  private @Nullable PClass superclass;

  private @Nullable Map allProperties;
  private @Nullable Map allMethods;

  public PClass(
      @Nullable String docComment,
      SourceLocation sourceLocation,
      Set modifiers,
      List annotations,
      PClassInfo classInfo,
      List typeParameters,
      Map properties,
      Map methods) {
    super(docComment, sourceLocation, modifiers, annotations, classInfo.getSimpleName());
    this.classInfo = classInfo;
    this.typeParameters = typeParameters;
    this.properties = properties;
    this.methods = methods;
  }

  public void initSupertype(PType supertype, PClass superclass) {
    this.supertype = supertype;
    this.superclass = superclass;
  }

  /**
   * Returns the name of the module that this class is declared in. Note that a module name is not
   * guaranteed to be unique, especially if it not declared but inferred from the module URI.
   */
  public String getModuleName() {
    return classInfo.getModuleName();
  }

  /**
   * Returns the qualified name of this class, `moduleName#className`. Note that a qualified class
   * name is not guaranteed to be unique, especially if the module name is not declared but inferred
   * from the module URI.
   */
  public String getQualifiedName() {
    return classInfo.getQualifiedName();
  }

  public String getDisplayName() {
    return classInfo.getDisplayName();
  }

  public PClassInfo getInfo() {
    return classInfo;
  }

  /** Tells if this class is the class of a module. */
  public boolean isModuleClass() {
    return getInfo().isModuleClass();
  }

  public List getTypeParameters() {
    return typeParameters;
  }

  public @Nullable PType getSupertype() {
    return supertype;
  }

  public @Nullable PClass getSuperclass() {
    return superclass;
  }

  public Map getProperties() {
    return properties;
  }

  public Map getMethods() {
    return methods;
  }

  public Map getAllProperties() {
    if (allProperties == null) {
      allProperties = collectAllProperties(this, new LinkedHashMap<>());
    }
    return allProperties;
  }

  public Map getAllMethods() {
    if (allMethods == null) {
      allMethods = collectAllMethods(this, new LinkedHashMap<>());
    }
    return allMethods;
  }

  @Override
  public void accept(ValueVisitor visitor) {
    visitor.visitClass(this);
  }

  @Override
  public  T accept(ValueConverter converter) {
    return converter.convertClass(this);
  }

  @Override
  public PClassInfo getClassInfo() {
    return PClassInfo.Class;
  }

  public String toString() {
    return getDisplayName();
  }

  public abstract static class ClassMember extends Member {
    @Serial private static final long serialVersionUID = 0L;

    private final PClass owner;

    public ClassMember(
        @Nullable String docComment,
        SourceLocation sourceLocation,
        Set modifiers,
        List annotations,
        String simpleName,
        PClass owner) {
      super(docComment, sourceLocation, modifiers, annotations, simpleName);
      this.owner = owner;
    }

    /**
     * @inheritDoc
     */
    @Override
    public String getModuleName() {
      return owner.getInfo().getModuleName();
    }

    /** Returns the class declaring this member. */
    public PClass getOwner() {
      return owner;
    }

    /**
     * Returns the documentation comment of this member. If this member does not have a
     * documentation comment, returns the documentation comment of the nearest documented ancestor,
     * if any.
     */
    public abstract @Nullable String getInheritedDocComment();
  }

  public static final class Property extends ClassMember {
    @Serial private static final long serialVersionUID = 0L;

    private final PType type;

    public Property(
        PClass owner,
        @Nullable String docComment,
        SourceLocation sourceLocation,
        Set modifiers,
        List annotations,
        String simpleName,
        PType type) {
      super(docComment, sourceLocation, modifiers, annotations, simpleName, owner);
      this.type = type;
    }

    public PType getType() {
      return type;
    }

    @Override
    public @Nullable String getInheritedDocComment() {
      if (getDocComment() != null) return getDocComment();

      for (var clazz = getOwner().getSuperclass(); clazz != null; clazz = clazz.getSuperclass()) {
        var property = clazz.getProperties().get(getSimpleName());
        if (property != null && property.getDocComment() != null) {
          return property.getDocComment();
        }
      }

      return null;
    }
  }

  public static final class Method extends ClassMember {
    @Serial private static final long serialVersionUID = 0L;

    private final List typeParameters;
    private final Map parameters;
    private final PType returnType;

    public Method(
        PClass owner,
        @Nullable String docComment,
        SourceLocation sourceLocation,
        Set modifiers,
        List annotations,
        String simpleName,
        List typeParameters,
        Map parameters,
        PType returnType) {
      super(docComment, sourceLocation, modifiers, annotations, simpleName, owner);
      this.typeParameters = typeParameters;
      this.parameters = parameters;
      this.returnType = returnType;
    }

    public List getTypeParameters() {
      return typeParameters;
    }

    public Map getParameters() {
      return parameters;
    }

    public PType getReturnType() {
      return returnType;
    }

    @Override
    public @Nullable String getInheritedDocComment() {
      if (getDocComment() != null) return getDocComment();

      for (var clazz = getOwner().getSuperclass(); clazz != null; clazz = clazz.getSuperclass()) {
        var method = clazz.getMethods().get(getSimpleName());
        if (method != null && method.getDocComment() != null) {
          return method.getDocComment();
        }
      }

      return null;
    }
  }

  private Map collectAllProperties(
      PClass clazz, Map collector) {
    if (clazz.superclass != null) {
      collectAllProperties(clazz.superclass, collector);
    }
    collector.putAll(clazz.properties);
    return collector;
  }

  private Map collectAllMethods(PClass clazz, Map collector) {
    if (clazz.superclass != null) {
      collectAllMethods(clazz.superclass, collector);
    }
    collector.putAll(clazz.methods);
    return collector;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy