refactor: improve URLDetector readability

- UrlDetector: simplify space handler in readDefault() — both branches
  of if/else were calling the same readEnd(InvalidUrl), making the
  conditional dead code; now we always call readEnd after attempting
  to read the domain
- UrlDetector: remove redundant inner buffer.isNotEmpty() check in
  readEnd(), already guarded by the outer condition
- UrlDetector: rename processColon() parameter from length to
  startLength to eliminate the var length = length self-shadowing
- UrlDetector: replace ArrayList<Url>() with mutableListOf<Url>()
  for idiomatic Kotlin
- DomainNameReader: replace lastSection.deleteRange(0, lastSection.length)
  with lastSection.clear() which expresses the intent directly
- DomainNameReader: move isDotPercent() and isXn() extension functions
  from inside the class body to private file-level functions — extension
  functions defined on a class instance are unusual and confusing

https://claude.ai/code/session_01Pci2AC45yQxQw6F6g7jWdd
This commit is contained in:
Claude
2026-03-08 00:54:38 +00:00
parent 46d54d2826
commit 812f465608
2 changed files with 21 additions and 27 deletions
@@ -30,6 +30,17 @@ import com.vitorpamplona.quartz.utils.urldetector.detection.CharUtils.splitByDot
import kotlin.math.max
import kotlin.math.min
/** Returns true if the string is a percent-encoded dot (%2e or %2E). */
private fun String.isDotPercent() = this == "%2e" || this == "%2E"
/** Returns true if the string is an internationalized domain label using Punycode (xn-- prefix). */
private fun String.isXn() =
this.length > 3 &&
(this[0] == 'x' || this[0] == 'X') &&
(this[1] == 'n' || this[1] == 'N') &&
this[2] == '-' &&
this[3] == '-'
/**
* The domain name reader reads input from a InputTextReader and validates if the content being read is a valid domain name.
* After a domain name is read, the returning status is what to do next. If the domain is valid but a specific character is found,
@@ -134,7 +145,6 @@ class DomainNameReader(
var isIpV6 = false
private set
fun String.isDotPercent() = this == "%2e" || this == "%2E"
/**
* Reads and parses the current string to make sure the domain name started where it was supposed to,
@@ -424,13 +434,6 @@ class DomainNameReader(
return checkDomainNameValid(ReaderNextState.ValidDomainName, null)
}
fun String.isXn() =
this.length > 3 &&
(this[0] == 'x' || this[0] == 'X') &&
(this[1] == 'n' || this[1] == 'N') &&
this[2] == '-' &&
this[3] == '-'
fun labelCount() = dots + (if (currentLabelLength > 0) 1 else 0)
/**
@@ -700,7 +703,7 @@ class DomainNameReader(
hexSection = true // reset hex to true
hexDigits = 0 // reset count for hex digits
numSections++
lastSection.deleteRange(0, lastSection.length) // clear last section
lastSection.clear() // clear last section
}
else -> {
@@ -52,7 +52,7 @@ class UrlDetector(
/**
* Stores the found urls.
*/
private val urlList: ArrayList<Url> = ArrayList<Url>()
private val urlList = mutableListOf<Url>()
/**
* Keeps track of certain indices to create a Url object.
@@ -89,18 +89,12 @@ class UrlDetector(
// read the next char to process.
when (val curr = reader.read()) {
' ' -> {
// space was found, check if it's a valid single level domain.
// space found; if we have a scheme, attempt to read the domain before resetting
if (buffer.isNotEmpty() && hasScheme) {
reader.goBack()
val domain = buffer.substring(length)
if (!readDomainName(domain)) {
readEnd(ReadEndState.InvalidUrl)
} else {
readEnd(ReadEndState.InvalidUrl)
}
} else {
readEnd(ReadEndState.InvalidUrl)
readDomainName(buffer.substring(length))
}
readEnd(ReadEndState.InvalidUrl)
length = 0
}
@@ -220,8 +214,8 @@ class UrlDetector(
* @param length first index of the previous part (could be beginning of the buffer, beginning of the username/password, or beginning
* @return new index of where the domain starts
*/
private fun processColon(length: Int): Int {
var length = length
private fun processColon(startLength: Int): Int {
var length = startLength
if (hasScheme) {
// read it as username/password if it has scheme
if (!readUserPass(length)) {
@@ -648,12 +642,9 @@ class UrlDetector(
private fun readEnd(state: ReadEndState?): Boolean {
// if the url is valid and greater then 0
if (state == ReadEndState.ValidUrl && buffer.isNotEmpty()) {
// Add the url to the list of good urls.
if (buffer.isNotEmpty()) {
var url = buffer.toString()
if (url.lastOrNull() in CANNOT_END_URLS_WITH) url = url.dropLast(1)
urlList.add(currentUrlMarker.createUrl(url))
}
var url = buffer.toString()
if (url.lastOrNull() in CANNOT_END_URLS_WITH) url = url.dropLast(1)
urlList.add(currentUrlMarker.createUrl(url))
}
// clear out the buffer.