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

merger.CodeSnipitLocation Maven / Gradle / Ivy

/*
 * Copyright 2019 by Daan van den Heuvel.
 *
 * This file is part of JavaForger.
 *
 * 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 merger;

import java.util.Optional;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc;
import com.github.javaparser.javadoc.Javadoc;

/**
 * Defines the location of a code block with an inclusive start line number and an exclusive end line number.
 *
 * @author Daan
 */
public class CodeSnipitLocation implements Comparable {

  /** start of the {@link CodeSnipitLocation} (inclusive), first possible line number is '1' */
  private final int start;
  /** end of the {@link CodeSnipitLocation} (exclusive) */
  private final int end;

  /**
   * @param start {@link CodeSnipitLocation#start}
   * @param end {@link CodeSnipitLocation#end}
   */
  public CodeSnipitLocation(int start, int end) {
    this.start = start;
    this.end = end;
  }

  /**
   * @see CodeSnipitLocation#start
   */
  public int getStart() {
    return start;
  }

  /**
   * @see CodeSnipitLocation#end
   */
  public int getEnd() {
    return end;
  }

  /**
   * @return the start line number minus one. Mend to be used in combination with arrays of strings.
   */
  public int getFirstIndex() {
    return start - 1;
  }

  /**
   * @return the end line number minus one. Mend to be used in combination with arrays of strings.
   */
  public int getLastIndex() {
    return end - 1;
  }

  /**
   * @return {@code true} if the end line is higher than the start line, {@code false} otherwise.
   */
  public boolean containsLines() {
    return end > start;
  }

  /**
   * @return The total number of lines represented by this {@link CodeSnipitLocation}.
   */
  public int size() {
    return end - start;
  }

  /**
   * Creates a new {@link CodeSnipitLocation}.
   *
   * @param start The {@link CodeSnipitLocation#start}
   * @param end The {@link CodeSnipitLocation#end}
   * @return new {@link CodeSnipitLocation}
   */
  public static CodeSnipitLocation of(int start, int end) {
    return new CodeSnipitLocation(start, end);
  }

  /**
   * Creates a new {@link CodeSnipitLocation} of a single line.
   *
   * @param startEnd The {@link CodeSnipitLocation#start} and {@link CodeSnipitLocation#end}
   * @return new {@link CodeSnipitLocation}
   */
  public static CodeSnipitLocation of(int startEnd) {
    return of(startEnd, startEnd);
  }

  /**
   * Creates a new {@link CodeSnipitLocation} for the given {@link Node}.
   *
   * @param node The {@link JavaParser} {@link Node} used to determine the beginning and end of the node. Javadoc is not taken into account.
   * @return new {@link CodeSnipitLocation}.
   */
  public static CodeSnipitLocation of(Node node) {
    int javaDocLines = countJavaDocLines(node);
    CodeSnipitLocation location = of(node.getBegin().get().line - javaDocLines, node.getEnd().get().line + 1);
    return location;
  }

  /**
   * Creates a new {@link CodeSnipitLocation} representing the line directly above the given {@link JavaParser} {@link Node}.
   *
   * @param node the {@link JavaParser} {@link Node}.
   * @return a new {@link CodeSnipitLocation}.
   */
  public static CodeSnipitLocation before(Node node) {
    return of(node.getBegin().get().line);
  }

  /**
   * Creates a new {@link CodeSnipitLocation} representing the line directly below the given {@link JavaParser} {@link Node}.
   *
   * @param node the {@link JavaParser} {@link Node}.
   * @return a new {@link CodeSnipitLocation}.
   */
  public static CodeSnipitLocation after(Node node) {
    return of(node.getEnd().get().line + 1);
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + end;
    result = prime * result + start;
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    CodeSnipitLocation other = (CodeSnipitLocation) obj;
    if (end != other.end)
      return false;
    if (start != other.start)
      return false;
    return true;
  }

  @Override
  public String toString() {
    ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
    builder.append("start", start).append("end", end);
    return builder.toString();
  }

  @Override
  public int compareTo(CodeSnipitLocation that) {
    return this.start - that.start;
  }

  private static int countJavaDocLines(Node node) {
    int javaDocLines = 0;
    if (NodeWithJavadoc.class.isAssignableFrom(node.getClass())) {
      NodeWithJavadoc javaDocNode = (NodeWithJavadoc) node;
      Optional javadoc = javaDocNode.getJavadoc();
      if (javadoc.isPresent()) {
        String text = javadoc.get().toText();
        String[] lines = text.split("\r\n|\r|\n");
        javaDocLines = lines.length + 2; // The plus 2 is for the begin and end lines containing /** and */.

        // TODO it is currently not supported to have only a single line of javadoc.
      }
    }
    return javaDocLines;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy