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

com.oracle.truffle.api.source.SourceSection Maven / Gradle / Ivy

Go to download

Truffle is a multi-language framework for executing dynamic languages that achieves high performance when combined with Graal.

There is a newer version: 1.0.0-rc7
Show newest version
/*
 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.truffle.api.source;

/**
 * Description of contiguous section of text within a {@link Source} of program code.; supports
 * multiple modes of access to the text and its location.
 * 

* Two available source sections are considered equal if their sources, start and length are equal. * {@link #isAvailable() Unavailable} source sections are compared by identity. Source sections can * be used as keys in hash maps. * * @see Source#createSection(int) * @see Source#createSection(int, int) * @see Source#createSection(int, int, int) * @see Source#createUnavailableSection() * @since 0.8 or earlier */ public final class SourceSection { private final Source source; private final int charIndex; private final int charLength; // -1 indicates unavailable SourceSection(Source source, int charIndex, int charLength) { this.source = source; this.charIndex = charIndex; this.charLength = charLength; } /** * Returns whether this is a special instance that signifies that source information is * available. Unavailable source sections can be created using * {@link Source#createUnavailableSection()}. Available source sections are never equal to * unavailable source sections. Unavailable source sections return the same indices and lengths * as empty source sections starting at character index 0. * * @see Source#createUnavailableSection() * @since 0.18 */ public boolean isAvailable() { return charLength != -1; } /** * Returns whether the source section is in bounds of the {@link #getSource() source} * {@link Source#getCharacters() code}. Please note that calling this method causes the * {@link Source#getCharacters() code} of the {@link #getSource() source} to be loaded if it was * not yet loaded. */ boolean isValid() { return isAvailable() ? (charIndex + charLength <= getSource().getCharacters().length()) : false; } /** * Representation of the source program that contains this section. * * @return the source object * @since 0.8 or earlier */ public Source getSource() { return source; } /** * Returns 1-based line number of the first character in this section (inclusive). Returns * 1 for out of bounds or {@link #isAvailable() unavailable} source sections. * Please note that calling this method causes the {@link Source#getCharacters() code} of the * {@link #getSource() source} to be loaded if it was not yet loaded. * * @return the starting line number * @since 0.8 or earlier */ public int getStartLine() { if (source == null) { return -1; } if (!isValid()) { return 1; } return source.getLineNumber(getCharIndex()); } /** * Returns the 1-based column number of the first character in this section (inclusive). Returns * 1 for out of bounds or {@link #isAvailable() unavailable} source sections. * Please note that calling this method causes the {@link Source#getCharacters() code} of the * {@link #getSource() source} to be loaded if it was not yet loaded. * * @return the starting column number * @since 0.8 or earlier */ public int getStartColumn() { if (source == null) { return -1; } if (!isValid()) { return 1; } return source.getColumnNumber(getCharIndex()); } /** * Returns 1-based line number of the last character in this section (inclusive). Returns * 1 for out of bounds or {@link #isAvailable() unavailable} source sections. * Please note that calling this method causes the {@link Source#getCharacters() code} of the * {@link #getSource() source} to be loaded if it was not yet loaded. * * @return the starting line number * @since 0.8 or earlier */ public int getEndLine() { if (source == null) { return -1; } if (!isValid()) { return 1; } return source.getLineNumber(getCharIndex() + Math.max(0, getCharLength() - 1)); } /** * Returns the 1-based column number of the last character in this section (inclusive). Returns * 1 for out of bounds or {@link #isAvailable() unavailable} source sections. * Please note that calling this method causes the {@link Source#getCharacters() code} of the * {@link #getSource() source} to be loaded if it was not yet loaded. * * @return the starting column number * @since 0.8 or earlier */ public int getEndColumn() { if (source == null) { return -1; } if (!isValid()) { return 1; } return source.getColumnNumber(getCharIndex() + Math.max(0, getCharLength() - 1)); } /** * Returns the 0-based index of the first character in this section. Returns 0 for * {@link #isAvailable() unavailable} source sections. Please note that calling this method does * not cause the {@link Source#getCharacters() code} of the {@link #getSource() source} to be * loaded. The returned index might be out of bounds of the source code if assertions (-ea) are * not enabled. * * @return the starting character index * @since 0.8 or earlier */ public int getCharIndex() { return charIndex; } /** * Returns the length of this section in characters. Returns 0 for * {@link #isAvailable() unavailable} source sections. Please note that calling this method does * not cause the {@link Source#getCharacters() code} of the {@link #getSource() source} to be * loaded. The returned length might be out of bounds of the source code if assertions (-ea) are * not enabled. * * @return the number of characters in the section * @since 0.8 or earlier */ public int getCharLength() { if (source == null) { return -1; } return charLength == -1 ? 0 : charLength; } /** * Returns the index of the text position immediately following the last character in the * section. Returns 0 for {@link #isAvailable() unavailable} source sections. * Please note that calling this method does not cause the {@link Source#getCharacters() code} * of the {@link #getSource() source} to be loaded. The returned index might be out of bounds of * the source code if assertions (-ea) are not enabled. * * @return the end position of the section * @since 0.8 or earlier */ public int getCharEndIndex() { if (source == null) { return -1; } return getCharIndex() + getCharLength(); } /** * Returns the source code fragment described by this section. Returns an empty character * sequence for out of bounds or {@link #isAvailable() unavailable} source sections. Please note * that calling this method causes the {@link Source#getCharacters() code} of the * {@link #getSource() source} to be loaded if it was not yet loaded. * * @return the code as a CharSequence * @since 0.28 */ public CharSequence getCharacters() { if (!isValid()) { return ""; } return source.getCharacters().subSequence(getCharIndex(), getCharEndIndex()); } /** * Returns an implementation-defined string representation of this source section to be used for * debugging purposes only. * * @see #getCharacters() * @since 0.8 or earlier */ @Override public String toString() { StringBuilder b = new StringBuilder(); b.append("SourceSection(source=").append(getSource().getName()); if (isAvailable()) { b.append(", index=").append(getCharIndex()); b.append(", length=").append(getCharLength()); if (isValid()) { b.append(", characters=").append(getCharacters().toString().replaceAll("\\n", "\\\\n")); } else { b.append(", valid=false"); } } else { b.append(" available=false"); } b.append(")"); return b.toString(); } /** @since 0.8 or earlier */ @Override public int hashCode() { if (!isAvailable()) { return System.identityHashCode(this); } final int prime = 31; int result = 1; result = prime * result + charIndex; result = prime * result + charLength; result = prime * result + source.hashCode(); return result; } /** @since 0.8 or earlier */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof SourceSection)) { return false; } SourceSection other = (SourceSection) obj; if (!isAvailable()) { // Unavailable SourceSections are compared by identity return this == obj; } if (charIndex != other.charIndex) { return false; } if (charLength != other.charLength) { return false; } if (source == null) { if (other.source != null) { return false; } } else if (!source.equals(other.source)) { return false; } return true; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy