001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2026 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018///////////////////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.grammar;
021
022import java.io.Serial;
023import java.util.Objects;
024
025import org.antlr.v4.runtime.CommonToken;
026import org.antlr.v4.runtime.Token;
027
028/**
029 * A simple wrapper for ANTLR {@link Token} that provides a proper {@link #equals(Object)}
030 * and {@link #hashCode()} implementation based on the token's {@code type} and {@code text}.
031 *
032 * <p>This is useful because ANTLR's default {@code CommonToken} does not override
033 * {@code equals}, It compares references.
034 */
035public final class SimpleToken extends CommonToken {
036
037    /** A unique serial version identifier. */
038    @Serial
039    private static final long serialVersionUID = 1L;
040
041    /**
042     * Constructs a new instance from an existing ANTLR {@link Token}.
043     *
044     * @param token the ANTLR token to wrap
045     */
046    private SimpleToken(
047            Token token) {
048        super(token);
049        setTokenIndex(token.getTokenIndex());
050    }
051
052    /**
053     * Creates a new instance from an existing ANTLR {@link Token}.
054     *
055     * @param token the ANTLR token to wrap
056     * @return a new instance of SimpleToken wrapping the provided token
057     */
058    public static SimpleToken from(Token token) {
059        return new SimpleToken(token);
060    }
061
062    @Override
063    public boolean equals(Object obj) {
064        if (this == obj) {
065            return true;
066        }
067        if (obj == null) {
068            return false;
069        }
070        if (getClass() != obj.getClass()) {
071            return false;
072        }
073        final SimpleToken other = (SimpleToken) obj;
074        return getType() == other.getType()
075                && getText().equals(other.getText())
076                && getLine() == other.getLine()
077                && getTokenIndex() == other.getTokenIndex()
078                && getCharPositionInLine() == other.getCharPositionInLine()
079                && getStartIndex() == other.getStartIndex()
080                && getStopIndex() == other.getStopIndex();
081    }
082
083    @Override
084    public int hashCode() {
085        return Objects.hash(
086                getType(),
087                getText(),
088                getLine(),
089                getTokenIndex(),
090                getCharPositionInLine(),
091                getStartIndex(),
092                getStopIndex()
093        );
094    }
095
096}