Skip to content

Commit

Permalink
Added BOM detection and BOM marker removal
Browse files Browse the repository at this point in the history
If a source code uses encoding with BOM marker, this marker becomes a part of a prefix in a JS.CompilationUnit.
During the equality check on the Java side (org.openrewrite.Parser.requirePrintEqualsInput) between the source code and the code generated based on the LST, Java trims the BOM marker.
So this causes an idempotency error.

Therefore, we also detect and trim the BOM marker on a JS/TS parser side from JS.CompilationUnit prefix.
  • Loading branch information
Andrii Rodionov committed Jan 8, 2025
1 parent 2d8ec7c commit 779c678
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions openrewrite/src/javascript/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,45 @@ export class JavaScriptParserVisitor {
return this.visit(node) as T;
}

detectBOMAndTextEncoding(content: String) : { hasBom: boolean; encoding: string | null } {
const BOM_UTF8 = "\uFEFF"; // BOM for UTF-8
const BOM_UTF16_LE = [0xFF, 0xFE]; // BOM for UTF-16 Little Endian

// Detect BOM
const hasUtf8Bom = content.startsWith(BOM_UTF8);
const hasUtf16LeBom = content.charCodeAt(0) === BOM_UTF16_LE[0] && content.charCodeAt(1) === BOM_UTF16_LE[1];

if (hasUtf8Bom) {
return { hasBom: true, encoding: 'utf8' };
} else if (hasUtf16LeBom) {
return { hasBom: true, encoding: 'utf16le' };
}

return { hasBom: false, encoding: null };
}

visitSourceFile(node: ts.SourceFile): JS.CompilationUnit {

let bomAndTextEncoding = this.detectBOMAndTextEncoding(node.getFullText());

let prefix = this.prefix(node);
if (bomAndTextEncoding.hasBom) {
// If a node full text has a BOM marker, it becomes a part of the prefix, so we remove it
if (bomAndTextEncoding.encoding === 'utf8') {
prefix = prefix.withWhitespace(prefix.whitespace!.slice(1));
} else if (bomAndTextEncoding.encoding === 'utf16le') {
prefix = prefix.withWhitespace(prefix.whitespace!.slice(2));
}
}

return new JS.CompilationUnit(
randomId(),
this.prefix(node),
prefix,
Markers.EMPTY,
this.sourceFile.fileName,
null,
null,
false,
bomAndTextEncoding.encoding,
bomAndTextEncoding.hasBom,
null,
[],
this.semicolonPaddedStatementList(node.statements),
Expand Down

0 comments on commit 779c678

Please sign in to comment.