Skip to content

Commit 1696440

Browse files
committed
NEW @W-19374413@ Fixed test
1 parent 384f309 commit 1696440

File tree

5 files changed

+44
-12
lines changed

5 files changed

+44
-12
lines changed

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44
# See https://help.github.com/articles/dealing-with-line-endings/
55
*.goldfile.* text eol=lf
66

7+
# Some of our input files must be forced to use a certain EOL signifier no matter what the OS wants.
8+
# So we forcefully set any file that includes lf or crlf in its file extension to use the corresponding EOL.
79
*.lf.* text eol=lf
10+
*.crlf.* text eol=crlf

packages/code-analyzer-regex-engine/src/engine.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
import path from "node:path";
1212
import fs from "node:fs";
1313
import * as fsp from 'node:fs/promises';
14-
import os from "node:os";
1514
import {RegexRule, RegexRules} from "./config";
1615
import {isBinaryFile} from "isbinaryfile";
1716
import {convertToRegex, PromiseExecutionLimiter} from "./utils";
@@ -137,7 +136,8 @@ export class RegexEngine extends Engine {
137136
private async scanFileContents(fileName: string, fileContents: string, ruleName: string): Promise<Violation[]> {
138137
const violations: Violation[] = [];
139138
const regex: RegExp = this.getRegExpFor(ruleName);
140-
const newlineIndexes: number[] = getNewlineIndices(fileContents);
139+
const contextuallyDerivedEol: string = contextuallyDeriveEolString(fileContents);
140+
const newlineIndexes: number[] = getNewlineIndices(fileContents, contextuallyDerivedEol);
141141

142142
for (const match of fileContents.matchAll(regex)) {
143143
let startIndex: number = match.index;
@@ -151,9 +151,9 @@ export class RegexEngine extends Engine {
151151
}
152152

153153
const startLine: number = getLineNumber(startIndex, newlineIndexes);
154-
const startColumn: number = getColumnNumber(startIndex, newlineIndexes);
154+
const startColumn: number = getColumnNumber(startIndex, newlineIndexes, contextuallyDerivedEol);
155155
const endLine: number = getLineNumber(startIndex + matchLength, newlineIndexes);
156-
const endColumn: number = getColumnNumber(startIndex + matchLength, newlineIndexes);
156+
const endColumn: number = getColumnNumber(startIndex + matchLength, newlineIndexes, contextuallyDerivedEol);
157157
const codeLocation: CodeLocation = {
158158
file: fileName,
159159
startLine: startLine,
@@ -180,13 +180,13 @@ export class RegexEngine extends Engine {
180180
}
181181

182182

183-
function getColumnNumber(charIndex: number, newlineIndexes: number[]): number {
183+
function getColumnNumber(charIndex: number, newlineIndexes: number[], contextuallyDerivedEol: string): number {
184184
const idxOfNextNewline = newlineIndexes.findIndex(el => el >= charIndex);
185185
const idxOfCurrentLine = idxOfNextNewline === -1 ? newlineIndexes.length - 1: idxOfNextNewline - 1;
186186
if (idxOfCurrentLine === 0){
187187
return charIndex + 1;
188188
} else {
189-
const eolOffset = os.EOL.length - 1;
189+
const eolOffset = contextuallyDerivedEol.length - 1;
190190
return charIndex - newlineIndexes.at(idxOfCurrentLine)! - eolOffset;
191191
}
192192
}
@@ -196,8 +196,8 @@ function getLineNumber(charIndex: number, newlineIndexes: number[]): number{
196196
return idxOfNextNewline === -1 ? newlineIndexes.length : idxOfNextNewline;
197197
}
198198

199-
function getNewlineIndices(fileContents: string): number[] {
200-
const newlineRegex: RegExp = new RegExp(os.EOL, "g");
199+
function getNewlineIndices(fileContents: string, contextuallyDerivedEol: string): number[] {
200+
const newlineRegex: RegExp = new RegExp(contextuallyDerivedEol, "g");
201201
const matches = fileContents.matchAll(newlineRegex);
202202
const newlineIndexes = [-1];
203203

@@ -207,6 +207,15 @@ function getNewlineIndices(fileContents: string): number[] {
207207
return newlineIndexes;
208208
}
209209

210+
/**
211+
* We can't assume that the file's EOL indicator matches the OS's, because of edge cases such as a file created on Unix
212+
* but scanned on Windows. So instead of consulting the OS for the EOL indicator, we look at the file and find which one it uses.
213+
* @param contents
214+
*/
215+
function contextuallyDeriveEolString(contents: string): string {
216+
return contents.indexOf('\r\n') !== -1 ? '\r\n' : '\n';
217+
}
218+
210219
async function isTextFile(fileName: string): Promise<boolean> {
211220
const ext: string = path.extname(fileName).toLowerCase();
212221
return TEXT_BASED_FILE_EXTS.has(ext) || !(await isBinaryFile(fileName));

packages/code-analyzer-regex-engine/test/engine.test.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const SAMPLE_CUSTOM_RULES: RegexRules = {
3939
NoTalkingAboutFightClub: {
4040
regex: '/fight club/gi',
4141
description: "The first rule of Fight Club is do not talk about Fight Club",
42-
file_extensions: [".abc-def.xyz", ".lf.cls"],
42+
file_extensions: [".abc-def.xyz", ".lf.cls", ".crlf.cls"],
4343
violation_message: "The second rule of Fight Club is DO NOT. TALK. ABOUT FIGHT CLUB.",
4444
severity: DEFAULT_SEVERITY_LEVEL,
4545
tags: ['PopCulture']
@@ -783,9 +783,9 @@ describe('Tests for runRules', () => {
783783
}
784784
});
785785

786-
it('When workspace contains files that use \\n instead of \\r\\n, violations are right regardless of OS', async () => {
786+
it('When files indicate EOL differently than OS, violations are still correct', async () => {
787787
const runOptions: RunOptions = createRunOptions(
788-
new Workspace('id', [path.resolve(__dirname, "test-data", "workspaceWithLfNewlines")]));
788+
new Workspace('id', [path.resolve(__dirname, "test-data", "workspaceWithOddNewlines")]));
789789
const runResults: EngineRunResults = await engine.runRules(['NoTalkingAboutFightClub'], runOptions);
790790

791791
const expectedViolations: Violation[] = [
@@ -795,7 +795,21 @@ describe('Tests for runRules', () => {
795795
primaryLocationIndex: 0,
796796
codeLocations: [
797797
{
798-
file: path.resolve(__dirname, "test-data", "workspaceWithLfNewlines", "testClass.lf.cls"),
798+
file: path.resolve(__dirname, "test-data", "workspaceWithOddNewlines", "testClass.lf.cls"),
799+
startLine: 3,
800+
startColumn: 87,
801+
endLine: 3,
802+
endColumn: 97
803+
}
804+
]
805+
},
806+
{
807+
ruleName: "NoTalkingAboutFightClub",
808+
message: "The second rule of Fight Club is DO NOT. TALK. ABOUT FIGHT CLUB.",
809+
primaryLocationIndex: 0,
810+
codeLocations: [
811+
{
812+
file: path.resolve(__dirname, "test-data", "workspaceWithOddNewlines", "testClass.crlf.cls"),
799813
startLine: 3,
800814
startColumn: 87,
801815
endLine: 3,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public class TestClass{
2+
public static boolean doTheThing() {
3+
List<String> strings = new List<String>{'This is fine', 'This is also fine', 'fight club', 'OH NO, that last string was bad!'};
4+
return false;
5+
}
6+
}

packages/code-analyzer-regex-engine/test/test-data/workspaceWithLfNewlines/testClass.lf.cls renamed to packages/code-analyzer-regex-engine/test/test-data/workspaceWithOddNewlines/testClass.lf.cls

File renamed without changes.

0 commit comments

Comments
 (0)