canTokensBeAdjacent(leftValue, rightValue) {
		const espreeOptions = {
			ecmaVersion: espree.latestEcmaVersion,
			comment: true,
			range: true,
		};

		let leftToken;

		if (typeof leftValue === "string") {
			let tokens;

			try {
				tokens = espree.tokenize(leftValue, espreeOptions);
			} catch {
				return false;
			}

			const comments = tokens.comments;

			leftToken = tokens.at(-1);
			if (comments.length) {
				const lastComment = comments.at(-1);

				if (!leftToken || lastComment.range[0] > leftToken.range[0]) {
					leftToken = lastComment;
				}
			}
		} else {
			leftToken = leftValue;
		}

		/*
		 * If a hashbang comment was passed as a token object from SourceCode,
		 * its type will be "Shebang" because of the way ESLint itself handles hashbangs.
		 * If a hashbang comment was passed in a string and then tokenized in this function,
		 * its type will be "Hashbang" because of the way Espree tokenizes hashbangs.
		 */
		if (leftToken.type === "Shebang" || leftToken.type === "Hashbang") {
			return false;
		}

		let rightToken;

		if (typeof rightValue === "string") {
			let tokens;

			try {
				tokens = espree.tokenize(rightValue, espreeOptions);
			} catch {
				return false;
			}

			const comments = tokens.comments;

			rightToken = tokens[0];
			if (comments.length) {
				const firstComment = comments[0];

				if (
					!rightToken ||
					firstComment.range[0] < rightToken.range[0]
				) {
					rightToken = firstComment;
				}
			}
		} else {
			rightToken = rightValue;
		}

		if (
			leftToken.type === "Punctuator" ||
			rightToken.type === "Punctuator"
		) {
			if (
				leftToken.type === "Punctuator" &&
				rightToken.type === "Punctuator"
			) {
				const PLUS_TOKENS = new Set(["+", "++"]);
				const MINUS_TOKENS = new Set(["-", "--"]);

				return !(
					(PLUS_TOKENS.has(leftToken.value) &&
						PLUS_TOKENS.has(rightToken.value)) ||
					(MINUS_TOKENS.has(leftToken.value) &&
						MINUS_TOKENS.has(rightToken.value))
				);
			}
			if (leftToken.type === "Punctuator" && leftToken.value === "/") {
				return !["Block", "Line", "RegularExpression"].includes(
					rightToken.type,
				);
			}
			return true;
		}

		if (
			leftToken.type === "String" ||
			rightToken.type === "String" ||
			leftToken.type === "Template" ||
			rightToken.type === "Template"
		) {
			return true;
		}

		if (
			leftToken.type !== "Numeric" &&
			rightToken.type === "Numeric" &&
			rightToken.value.startsWith(".")
		) {
			return true;
		}

		if (
			leftToken.type === "Block" ||
			rightToken.type === "Block" ||
			rightToken.type === "Line"
		) {
			return true;
		}

		if (rightToken.type === "PrivateIdentifier") {
			return true;
		}

		return false;
	}
Determines whether two tokens can safely be placed next to each other without merging into a single token
@param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used.
@param {Token|string} rightValue The right token. If this is a string, it will be tokenized and the first token will be used.
@returns {boolean} If the tokens cannot be safely placed next to each other, returns `false`. If the tokens can be placed
next to each other, behavior is undefined (although it should return `true` in most cases).