RFR: 8360070: AccessibleText.getBeforeIndex returns null for last character [v3]

Nikita Provotorov duke at openjdk.org
Tue Jul 15 10:24:49 UTC 2025


On Tue, 15 Jul 2025 03:58:55 GMT, Sergey Bylokhov <serb at openjdk.org> wrote:

>> I modified Abhishek's test:
>> 
>> 
>>             System.out.println(" i  bef   at  aft");
>>             for (int i : new int[] {0, 1, 2, 8, 9, 10}) {
>>                 System.out.printf("%2d%5s%5s%5s\n",
>>                                   i,
>>                                   at.getBeforeIndex(CHARACTER, i),
>>                                   at.getAtIndex(CHARACTER, i),
>>                                   at.getAfterIndex(CHARACTER, i));
>>             }
>> 
>> 
>> This way, I created a table of returned values:
>> 
>> 
>> Text: "0123456789"
>> Text Length: 10
>>  i  bef   at  aft
>>  0 null    0    1
>>  1    0    1    2
>>  2    1    2    3
>>  8    7    8    9
>>  9    8    9 null
>> 10 null null null
>> 
>> 
>> I'd expect to see 9 as the return value of `getBeforeIndex` for the index of 10. This would make the table symmetrical.
>> 
>> Therefore, I'm in favour for Abhishek's proposed fix.
>> 
>> ---
>> 
>> The description of the methods in `AccessibleText` is vague. None of the three methods specifies what the index means and what values are accepted for it.
>> 
>> According to the text model, index 10 is still valid, it's the index between the last character and the implied line break, so `tf.getDocument().getText(10, 1)` returns `\n`.
>> 
>> Having this in mind, the specification of the `getBeforeIndex`, `getAtIndex`, `getAfterIndex` methods should be updated to *explicitly specify the valid values for the `index` parameter*.
>
>>I'd expect to see 9 as the return value of getBeforeIndex for the index of 10. This would make the table symmetrical.
> 
> Why do you expect that? The spec states that the index should be "an index within the text." That index is also used in other methods, such as getCharacterBounds(), etc. If we fixed it only for text at the end, it would make the behavior even less symmetric, since for a negative value, the model will always throw an exception.
> 
>>According to the text model, index 10 is still valid, it's the index between the last character and the implied line break, so tf.getDocument().getText(10, 1) returns \n.
> 
> The last character is implementation detail, it is not part of the "users data" this is the reason why it is excluded from the Document.getLength(). So passing length as a last character might cause an exception for custom documents. We also have the getCharCount() methods which returns "the number of characters (valid indices)".
> 
> Also, why are we only talking about JTextComponent? There are other same implementations of AccessibleText for example [JLabel](https://github.com/openjdk/jdk/blob/0acd065bf5a75090b84c28b28856a62d86c52791/src/java.desktop/share/classes/javax/swing/JLabel.java#L1287).
> 
>>Here i disagree, the "within the text" does not imply that the position behind the last character is not within the text. Otherwise with the caret is at the end of the text it is impossible to request last word or character before the caret position which is one of the valid use cases of this accessibility method. I think the fix is valid.
> 
> It means exactly that, and it is also impossible to request the first character after the caret position if it is at the start of the document. For both cases getAtIndex() should work.

I agree with @mrserb: there already is `getAtIndex` and the documentation is clear about that the index should be within the text. From my side I'd add that changing this behavior may break backward-compatibility with client's custom AWT/Swing components.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/25941#issuecomment-3073048371


More information about the client-libs-dev mailing list