Skip to content

Commit 937fed5

Browse files
committed
Factorize logic into helpers and add tests
1 parent bc7dd15 commit 937fed5

File tree

3 files changed

+136
-60
lines changed

3 files changed

+136
-60
lines changed

integration/vscode/ada/src/gnatcov.ts

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as path from 'path';
66
import * as vscode from 'vscode';
77
import { CancellationToken } from 'vscode-languageclient';
88
import { adaExtState } from './extension';
9-
import { parallelize, staggerProgress } from './helpers';
9+
import { getMatchingPrefixes, parallelize, staggerProgress, toPosix } from './helpers';
1010

1111
/**
1212
* TypeScript types to represent data from GNATcoverage XML reports
@@ -426,44 +426,10 @@ export async function addCoverageData(run: vscode.TestRun, covDir: string) {
426426
const localAbsPath = srcUri.fsPath;
427427
const posixLocalAbsPath = toPosix(localAbsPath);
428428

429-
/**
430-
* Find the longest common prefix between both
431-
* paths by starting to compare the characters
432-
* from the end of each string and iterating
433-
* backwards.
434-
*/
435-
let revIndex = 0;
436-
while (
437-
revIndex < posixForeignPath.length &&
438-
revIndex < posixLocalAbsPath.length &&
439-
posixForeignPath[posixForeignPath.length - revIndex] ==
440-
posixLocalAbsPath[posixLocalAbsPath.length - revIndex]
441-
) {
442-
revIndex++;
443-
}
444-
445-
// Now the index points to the first different
446-
// character, so move it back to the last identical
447-
// character to make the slice operations below
448-
// more natural.
449-
revIndex--;
450-
451-
if (
452-
revIndex < posixForeignPath.length &&
453-
revIndex < posixLocalAbsPath.length
454-
) {
455-
posixLocalPrefix = posixLocalAbsPath.slice(
456-
0,
457-
posixLocalAbsPath.length - revIndex,
458-
);
459-
posixForeignPrefix = posixForeignPath.slice(
460-
0,
461-
posixForeignPath.length - revIndex,
462-
);
463-
} else {
464-
// Could not find a common prefix so don't
465-
// do anything
466-
}
429+
[posixForeignPrefix, posixLocalPrefix] = getMatchingPrefixes(
430+
posixForeignPath,
431+
posixLocalAbsPath,
432+
);
467433
}
468434

469435
const total = file.metric.find(
@@ -575,27 +541,6 @@ export class GnatcovFileCoverage extends vscode.FileCoverage {
575541
}
576542
}
577543

578-
/**
579-
*
580-
* @param p - a path
581-
* @returns a POSIX version of the same path obtained by replacing occurences
582-
* of `\` with `/`. If the input path was a Windows absolute path, a `/` is
583-
* prepended to the output to make it also an absolute path.
584-
*/
585-
function toPosix(p: string) {
586-
let posixPath = p.replace(RegExp(`\\${path.win32.sep}`, 'g'), path.posix.sep);
587-
588-
/**
589-
* If it was an absolute path from Windows, we have to
590-
* manually make it a POSIX absolute path.
591-
*/
592-
if (path.win32.isAbsolute(p) && !path.posix.isAbsolute(posixPath)) {
593-
posixPath = `/${posixPath}`;
594-
}
595-
596-
return posixPath;
597-
}
598-
599544
export function convertSourceReport(
600545
data: source_type,
601546
token?: CancellationToken,

integration/vscode/ada/src/helpers.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,3 +644,71 @@ export function staggerProgress(
644644
export function slugify(arg: string): string {
645645
return arg.replace(/[<>:"/\\|?*]/g, '_');
646646
}
647+
/**
648+
* @returns the length of the common suffix between the given strings. If there
649+
* is no common suffix, the result is `0`.
650+
*/
651+
export function getLengthCommonSuffix(str1: string, str2: string): number {
652+
/**
653+
* Compare characters from the end of each string and iterating backwards.
654+
*/
655+
let len = 0;
656+
while (
657+
len < str1.length &&
658+
len < str2.length &&
659+
str1[str1.length - 1 - len] == str2[str2.length - 1 - len]
660+
) {
661+
len++;
662+
}
663+
664+
return len;
665+
}
666+
667+
/**
668+
*
669+
* @param p - a path
670+
* @returns a POSIX version of the same path obtained by replacing occurences
671+
* of `\` with `/`. If the input path was a Windows absolute path, a `/` is
672+
* prepended to the output to make it also an absolute path.
673+
*/
674+
export function toPosix(p: string) {
675+
let posixPath = p.replace(RegExp(`\\${path.win32.sep}`, 'g'), path.posix.sep);
676+
677+
/**
678+
* If it was an absolute path from Windows, we have to
679+
* manually make it a POSIX absolute path.
680+
*/
681+
if (path.win32.isAbsolute(p) && !path.posix.isAbsolute(posixPath)) {
682+
posixPath = `/${posixPath}`;
683+
}
684+
685+
return posixPath;
686+
}
687+
688+
/**
689+
*
690+
* @param path1 - a path
691+
* @param path2 - another path
692+
* @returns if the given paths end with a common suffix, the remaining prefixes
693+
* are returned as a tuple by this function. Otherwise, undefined prefixes are
694+
* returned.
695+
*/
696+
export function getMatchingPrefixes(
697+
path1: string,
698+
path2: string,
699+
): [string | undefined, string | undefined] {
700+
const lenCommonSuffix = getLengthCommonSuffix(path1, path2);
701+
702+
let prefix1;
703+
let prefix2;
704+
705+
if (lenCommonSuffix > 0) {
706+
prefix1 = path1.slice(0, path1.length - lenCommonSuffix);
707+
prefix2 = path2.slice(0, path2.length - lenCommonSuffix);
708+
} else {
709+
// Could not find a common suffix
710+
prefix1 = prefix2 = undefined;
711+
}
712+
713+
return [prefix1, prefix2];
714+
}

integration/vscode/ada/test/general/helpers.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import assert from 'assert';
22
import {
33
envHasExec,
44
findAdaMain,
5+
getLengthCommonSuffix,
6+
getMatchingPrefixes,
57
getSymbols,
68
parallelize,
79
slugify,
810
staggerProgress,
11+
toPosix,
912
which,
1013
} from '../../src/helpers';
1114
import {
@@ -350,3 +353,63 @@ suite('staggerProgress', function () {
350353
assert.equal(slugify('file<>:"/\\|?*name'), 'file' + '_'.repeat(9) + 'name');
351354
});
352355
});
356+
357+
suite('getLengthCommonSuffix', function () {
358+
test('empty', function () {
359+
assert.equal(getLengthCommonSuffix('', ''), 0);
360+
});
361+
362+
test('one char', function () {
363+
assert.equal(getLengthCommonSuffix('a', ''), 0);
364+
assert.equal(getLengthCommonSuffix('', 'b'), 0);
365+
assert.equal(getLengthCommonSuffix('a', 'a'), 1);
366+
assert.equal(getLengthCommonSuffix('a', 'b'), 0);
367+
});
368+
test('two char', function () {
369+
assert.equal(getLengthCommonSuffix('ab', ''), 0);
370+
assert.equal(getLengthCommonSuffix('', 'ab'), 0);
371+
assert.equal(getLengthCommonSuffix('ab', 'a'), 0);
372+
assert.equal(getLengthCommonSuffix('ab', 'b'), 1);
373+
assert.equal(getLengthCommonSuffix('ab', 'ab'), 2);
374+
assert.equal(getLengthCommonSuffix('ab', 'cd'), 0);
375+
});
376+
test('more', function () {
377+
assert.equal(getLengthCommonSuffix('abcdefg', ''), 0);
378+
assert.equal(getLengthCommonSuffix('abcdefg', 'g'), 1);
379+
assert.equal(getLengthCommonSuffix('abcdefg', 'x'), 0);
380+
assert.equal(getLengthCommonSuffix('abcdefg', 'fg'), 2);
381+
assert.equal(getLengthCommonSuffix('abcdefg', 'abcdefg'), 7);
382+
});
383+
});
384+
385+
suite('toPosix', function () {
386+
test('Windows paths', function () {
387+
assert.equal(toPosix('C:\\some\\path'), '/C:/some/path');
388+
assert.equal(toPosix('C:\\some\\path\\'), '/C:/some/path/');
389+
assert.equal(toPosix(''), '');
390+
assert.equal(toPosix('C:\\'), '/C:/');
391+
assert.equal(toPosix('c:\\'), '/c:/');
392+
assert.equal(toPosix('a\\relative\\path'), 'a/relative/path');
393+
});
394+
test('POSIX paths', function () {
395+
assert.equal(toPosix('/'), '/');
396+
assert.equal(toPosix('/some/path'), '/some/path');
397+
assert.equal(toPosix('/some/path/'), '/some/path/');
398+
assert.equal(toPosix('a/relative/path'), 'a/relative/path');
399+
});
400+
});
401+
402+
suite('getMatchingPrefixes', function () {
403+
test('cases', function () {
404+
assert.deepStrictEqual(
405+
getMatchingPrefixes('/C:/a/b/common/part.adb', '/other/path/common/part.adb'),
406+
['/C:/a/b', '/other/path'],
407+
);
408+
assert.deepStrictEqual(
409+
getMatchingPrefixes('/C:/a/b/d/e', '/other/path/with/no/common/part'),
410+
[undefined, undefined],
411+
);
412+
assert.deepStrictEqual(getMatchingPrefixes('', ''), [undefined, undefined]);
413+
assert.deepStrictEqual(getMatchingPrefixes('a', 'a'), ['', '']);
414+
});
415+
});

0 commit comments

Comments
 (0)