{"record":{"id":"074fb5223ceba00a","repo":"antlr/antlr4","slug":"should-only-be-one-op-per-index","errorCode":null,"errorMessage":"should only be one op per index","messagePattern":"should only be one op per index","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"runtime/JavaScript/src/antlr4/TokenStreamRewriter.js","lineNumber":313,"sourceCode":"                    rop.text = this.catOpText(iop.text, rop.text);\n                    rewrites[i] = undefined;\t// delete current insert\n                    continue;\n                }\n                if (iop.index >= rop.index && iop.index <= rop.lastIndex) {\n                    throw new Error(`insert op ${iop} within boundaries of previous ${rop}`);\n                }\n            }\n        }\n\n        /** @type {Map<number, RewriteOperation>} */\n        let m = new Map();\n        for (let op of rewrites) {\n            if (op == null) {\n                // ignore deleted ops\n                continue;\n            }\n            if (m.get(op.index) != null) {\n                throw new Error(\"should only be one op per index\");\n            }\n            m.set(op.index, op);\n        }\n        return m;\n    }\n\n    /**\n     * @param {Text} a\n     * @param {Text} b\n     * @returns {string}\n     */\n    catOpText(a, b) {\n        let x = \"\";\n        let y = \"\";\n        if (a != null) {\n            x = a.toString();\n        }\n        if (b != null) {","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/JavaScript/src/antlr4/TokenStreamRewriter.js#L295-L331","documentation":"OrderedHashSet.remove(Object) is hard-coded to throw UnsupportedOperationException (with an empty message) because the class must keep its LinkedHashMap and backing elements list consistent; the ANTLR authors simply did not implement ordered removal. OrderedHashSet backs ParserRuleContext children sets and rule-stop-state bookkeeping, so removal was never needed by the runtime.","triggerScenarios":"Calling remove(Object o) on any OrderedHashSet instance, e.g. a rule context's children set, or an OrderedHashSet you instantiated yourself.","commonSituations":"Treating OrderedHashSet as a general-purpose Set implementation; refactoring application collections to OrderedHashSet and assuming the full Set contract is honored.","solutions":["Use java.util.LinkedHashSet (or ArrayDeque-based structure) if you need ordered removal semantics.","Call clear() and re-add the remaining elements when a full rebuild is acceptable.","Wrap the set in a class that exposes only the operations actually supported."],"exampleFix":"// before\nOrderedHashSet<Token> tokens = new OrderedHashSet<>();\ntokens.remove(t); // UnsupportedOperationException\n\n// after\nLinkedHashSet<Token> tokens = new LinkedHashSet<>();\ntokens.remove(t);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean supportsRemove(Collection<?> c) { return !(c instanceof OrderedHashSet); }","tryCatchPattern":"try {\n    set.remove(o);\n} catch (UnsupportedOperationException e) {\n    // rebuild instead of remove\n    Object keep = ...;\n    set.clear();\n    set.add(keep);\n}","preventionTips":["Do not use OrderedHashSet as a general Set in application code.","Prefer LinkedHashSet when ordered removal is required.","Encapsulate OrderedHashSet behind an interface exposing only supported operations."],"tags":["antlr","java","unsupported-operation","orderedhashset","partial-api"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}