From 62b9b556c8da6539bcea48dfe6adac875559c1d0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 12 Sep 2015 05:21:08 -0700 Subject: [PATCH 1/7] use sting templates --- src/harness/instrumenter.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/harness/instrumenter.ts b/src/harness/instrumenter.ts index 1c9b9af78d2..b1b1750b8a8 100644 --- a/src/harness/instrumenter.ts +++ b/src/harness/instrumenter.ts @@ -3,11 +3,15 @@ var fs: any = require('fs'); var path: any = require('path'); function instrumentForRecording(fn: string, tscPath: string) { - instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startRecord("' + fn + '");', 'ts.sys.endRecord();'); + instrument(tscPath, ` +ts.sys = Playback.wrapSystem(ts.sys); +ts.sys.startRecord("${ fn }");`, `ts.sys.endRecord();`); } function instrumentForReplay(logFilename: string, tscPath: string) { - instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startReplay("' + logFilename + '");'); + instrument(tscPath, ` +ts.sys = Playback.wrapSystem(ts.sys); +ts.sys.startReplay("${ logFilename }");`); } function instrument(tscPath: string, prepareCode: string, cleanupCode: string = '') { From 36acaff6dc238fb26b6ece20b1cbef1717abab31 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 12 Sep 2015 05:23:53 -0700 Subject: [PATCH 2/7] Add wrapSystem function --- src/harness/loggedIO.ts | 172 ++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 5a572e220b3..3d1833b061f 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -95,6 +95,8 @@ module Playback { export interface PlaybackIO extends Harness.IO, PlaybackControl { } + export interface PlaybackSystem extends ts.System, PlaybackControl { } + function createEmptyLog(): IOLog { return { timestamp: (new Date()).toString(), @@ -114,8 +116,10 @@ module Playback { }; } - function initWrapper(wrapper: PlaybackControl, underlying: T) { - Object.keys(underlying).forEach(prop => { + function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; + function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; + function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { + ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -135,6 +139,79 @@ module Playback { wrapper.startRecord = (fileNameBase) => { recordLogFileNameBase = fileNameBase; recordLog = createEmptyLog(); + + if (underlying.args !== undefined && typeof underlying.args !== "function") { + recordLog.arguments = underlying.args; + } + }; + + wrapper.startReplayFromFile = logFn => { + wrapper.startReplayFromString(underlying.readFile(logFn)); + }; + wrapper.endRecord = () => { + if (recordLog !== undefined) { + let i = 0; + let fn = () => recordLogFileNameBase + i + ".json"; + while (underlying.fileExists(fn())) i++; + underlying.writeFile(fn(), JSON.stringify(recordLog)); + recordLog = undefined; + } + }; + + wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( + (path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }), + memoize((path) => { + // If we read from the file, it must exist + if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { + return true; + } else { + return findResultByFields(replayLog.fileExists, { path: path }, false); + } + }) + ); + + wrapper.getExecutingFilePath = () => { + if (replayLog !== undefined) { + return replayLog.executingPath; + } else if (recordLog !== undefined) { + return recordLog.executingPath = underlying.getExecutingFilePath(); + } else { + return underlying.getExecutingFilePath(); + } + }; + + wrapper.getCurrentDirectory = () => { + if (replayLog !== undefined) { + return replayLog.currentDirectory || ""; + } else if (recordLog !== undefined) { + return recordLog.currentDirectory = underlying.getCurrentDirectory(); + } else { + return underlying.getCurrentDirectory(); + } + }; + + wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( + (path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }), + memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); + + wrapper.readFile = recordReplay(wrapper.readFile, underlying)( + (path) => { + let result = underlying.readFile(path); + let logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } }; + recordLog.filesRead.push(logEntry); + return result; + }, + memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents)); + + wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( + (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }), + (path, contents) => noOpReplay("writeFile")); + + wrapper.exit = (exitCode) => { + if (recordLog !== undefined) { + wrapper.endRecord(); + } + underlying.exit(exitCode); }; } @@ -227,93 +304,18 @@ module Playback { let wrapper: PlaybackIO = {}; initWrapper(wrapper, underlying); - wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlying.readFile(logFn)); - }; - wrapper.endRecord = () => { - if (recordLog !== undefined) { - let i = 0; - let fn = () => recordLogFileNameBase + i + ".json"; - while (underlying.fileExists(fn())) i++; - underlying.writeFile(fn(), JSON.stringify(recordLog)); - recordLog = undefined; - } - }; - - wrapper.args = () => { - if (replayLog !== undefined) { - return replayLog.arguments; - } else if (recordLog !== undefined) { - recordLog.arguments = underlying.args(); - } - return underlying.args(); - } - - wrapper.newLine = () => underlying.newLine(); - wrapper.useCaseSensitiveFileNames = () => underlying.useCaseSensitiveFileNames(); wrapper.directoryName = (path): string => { throw new Error("NotSupported"); }; - wrapper.createDirectory = path => { throw new Error("NotSupported"); }; + wrapper.createDirectory = (path): void => { throw new Error("NotSupported"); }; wrapper.directoryExists = (path): boolean => { throw new Error("NotSupported"); }; - wrapper.deleteFile = path => { throw new Error("NotSupported"); }; + wrapper.deleteFile = (path): void => { throw new Error("NotSupported"); }; wrapper.listFiles = (path, filter, options): string[] => { throw new Error("NotSupported"); }; - wrapper.log = text => underlying.log(text); - - wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - (path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }), - memoize((path) => { - // If we read from the file, it must exist - if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { - return true; - } else { - return findResultByFields(replayLog.fileExists, { path: path }, false); - } - }) - ); - - wrapper.getExecutingFilePath = () => { - if (replayLog !== undefined) { - return replayLog.executingPath; - } else if (recordLog !== undefined) { - return recordLog.executingPath = underlying.getExecutingFilePath(); - } else { - return underlying.getExecutingFilePath(); - } - }; - - wrapper.getCurrentDirectory = () => { - if (replayLog !== undefined) { - return replayLog.currentDirectory || ""; - } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlying.getCurrentDirectory(); - } else { - return underlying.getCurrentDirectory(); - } - }; - - wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - (path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }), - memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); - - wrapper.readFile = recordReplay(wrapper.readFile, underlying)( - (path) => { - let result = underlying.readFile(path); - let logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } }; - recordLog.filesRead.push(logEntry); - return result; - }, - memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents)); - - wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }), - (path, contents) => noOpReplay("writeFile")); - - wrapper.exit = (exitCode) => { - if (recordLog !== undefined) { - wrapper.endRecord(); - } - underlying.exit(exitCode); - }; return wrapper; } + + export function wrapSystem(underlying: ts.System): PlaybackSystem { + let wrapper: PlaybackSystem = {}; + initWrapper(wrapper, underlying); + return wrapper; + } } \ No newline at end of file From 0d126e2ad78252eb6584f2667758deb2b6a03a85 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 12 Sep 2015 14:40:05 -0700 Subject: [PATCH 3/7] add support for tsconfig files in the rwc instrumenter/replay --- src/harness/harness.ts | 8 ++++++++ src/harness/loggedIO.ts | 18 +++++++++++++++++- src/harness/rwcRunner.ts | 20 +++++++++++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index f65a4f88730..2493eec867b 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -428,6 +428,7 @@ module Harness { args(): string[]; getExecutingFilePath(): string; exit(exitCode?: number): void; + readDirectory(path: string, extension?: string, exclude?: string[]): string[]; } export var IO: IO; @@ -464,6 +465,7 @@ module Harness { export const directoryExists: typeof IO.directoryExists = fso.FolderExists; export const fileExists: typeof IO.fileExists = fso.FileExists; export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine; + export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude); export function createDirectory(path: string) { if (directoryExists(path)) { @@ -532,6 +534,8 @@ module Harness { export const fileExists: typeof IO.fileExists = fs.existsSync; export const log: typeof IO.log = s => console.log(s); + export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude); + export function createDirectory(path: string) { if (!directoryExists(path)) { fs.mkdirSync(path); @@ -730,6 +734,10 @@ module Harness { export function writeFile(path: string, contents: string) { Http.writeToServerSync(serverRoot + path, "WRITE", contents); } + + export function readDirectory(path: string, extension?: string, exclude?: string[]) { + return listFiles(path).filter(f => !extension || ts.fileExtensionIs(f, extension)); + } } } diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 3d1833b061f..38c9cc7e795 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -59,6 +59,12 @@ interface IOLog { path: string; result?: string; }[]; + directoriesRead: { + path: string, + extension: string, + exclude: string[], + result: string[] + }[]; } interface PlaybackControl { @@ -103,6 +109,7 @@ module Playback { arguments: [], currentDirectory: "", filesRead: [], + directoriesRead: [], filesWritten: [], filesDeleted: [], filesAppended: [], @@ -118,7 +125,7 @@ module Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; - function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { + function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -203,6 +210,15 @@ module Playback { }, memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents)); + wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)( + (path, extension, exclude) => { + let result = (underlying).readDirectory(path, extension, exclude); + let logEntry = { path, extension, exclude, result }; + recordLog.directoriesRead.push(logEntry); + return result; + }, + (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); + wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }), (path, contents) => noOpReplay("writeFile")); diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index a1aaeed3d55..8bfb8400c59 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -19,6 +19,11 @@ module RWC { } } + function isTsConfigFile(file: { path: string }): boolean { + const tsConfigFileName = "tsconfig.json"; + return file.path.substr(file.path.length - tsConfigFileName.length).toLowerCase() === tsConfigFileName; + } + export function runRWCTest(jsonPath: string) { describe("Testing a RWC project: " + jsonPath, () => { let inputFiles: { unitName: string; content: string; }[] = []; @@ -67,8 +72,17 @@ module RWC { runWithIOLog(ioLog, oldIO => { harnessCompiler.reset(); + let fileNames = opts.fileNames; + + let tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined); + if (tsconfigFile) { + let tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path); + let configParseResult = ts.parseConfigFile(tsconfigFileContents.content, Harness.IO, ts.getDirectoryPath(tsconfigFile.path)); + fileNames = configParseResult.fileNames; + } + // Load the files - ts.forEach(opts.fileNames, fileName => { + ts.forEach(fileNames, fileName => { inputFiles.push(getHarnessCompilerInputUnit(fileName)); }); @@ -79,6 +93,10 @@ module RWC { const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)); let inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath)); + if (isTsConfigFile(fileRead)) { + continue; + } + if (!Harness.isLibraryFile(fileRead.path)) { if (inInputList) { continue; From 7ae902d75ae6ef8b861bcdfde2dc1b0439b36123 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 13 Sep 2015 23:26:52 -0700 Subject: [PATCH 4/7] Handel compiler options correctelly --- src/harness/rwcRunner.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 8bfb8400c59..c6637562ce5 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -77,8 +77,10 @@ module RWC { let tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined); if (tsconfigFile) { let tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path); - let configParseResult = ts.parseConfigFile(tsconfigFileContents.content, Harness.IO, ts.getDirectoryPath(tsconfigFile.path)); + let parsedTsconfigFileContents = ts.parseConfigFileText(tsconfigFile.path, tsconfigFileContents.content); + let configParseResult = ts.parseConfigFile(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path)); fileNames = configParseResult.fileNames; + opts.options = ts.extend(opts.options, configParseResult.options); } // Load the files From d9112f5e989eb6d0e3b606ee73deff607a19b9e2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 13 Sep 2015 23:35:22 -0700 Subject: [PATCH 5/7] use resolvePath to handel relative references correctelly --- src/harness/loggedIO.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 38c9cc7e795..46a791944b6 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -270,7 +270,7 @@ module Playback { } function findResultByPath(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T { - let normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase(); + let normalizedName = ts.normalizePath(expectedPath).toLowerCase(); // Try to find the result through normal fileName for (let i = 0; i < logArray.length; i++) { if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) { @@ -286,6 +286,7 @@ module Playback { } } } + // If we got here, we didn't find a match if (defaultValue === undefined) { throw new Error("No matching result in log array for path: " + expectedPath); From c1e536f2555a7842ae9afa545f6661400f77d4d5 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 15 Sep 2015 12:33:45 -0700 Subject: [PATCH 6/7] code review comments --- src/harness/loggedIO.ts | 50 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 46a791944b6..d0801612500 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -147,7 +147,7 @@ module Playback { recordLogFileNameBase = fileNameBase; recordLog = createEmptyLog(); - if (underlying.args !== undefined && typeof underlying.args !== "function") { + if (typeof underlying.args !== "function") { recordLog.arguments = underlying.args; } }; @@ -166,13 +166,14 @@ module Playback { }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - (path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }), - memoize((path) => { + path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), + memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { return true; - } else { - return findResultByFields(replayLog.fileExists, { path: path }, false); + } + else { + return findResultByFields(replayLog.fileExists, { path }, false); } }) ); @@ -180,9 +181,11 @@ module Playback { wrapper.getExecutingFilePath = () => { if (replayLog !== undefined) { return replayLog.executingPath; - } else if (recordLog !== undefined) { + } + else if (recordLog !== undefined) { return recordLog.executingPath = underlying.getExecutingFilePath(); - } else { + } + else { return underlying.getExecutingFilePath(); } }; @@ -190,25 +193,27 @@ module Playback { wrapper.getCurrentDirectory = () => { if (replayLog !== undefined) { return replayLog.currentDirectory || ""; - } else if (recordLog !== undefined) { + } + else if (recordLog !== undefined) { return recordLog.currentDirectory = underlying.getCurrentDirectory(); - } else { + } + else { return underlying.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - (path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }), - memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); + path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), + memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( - (path) => { + path => { let result = underlying.readFile(path); - let logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } }; + let logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; }, - memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents)); + memoize(path => findResultByPath(wrapper, replayLog.filesRead, path).contents)); wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)( (path, extension, exclude) => { @@ -220,7 +225,7 @@ module Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }), + (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), (path, contents) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { @@ -236,9 +241,11 @@ module Playback { return (function () { if (replayLog !== undefined) { return replay.apply(undefined, arguments); - } else if (recordLog !== undefined) { + } + else if (recordLog !== undefined) { return record.apply(undefined, arguments); - } else { + } + else { return original.apply(underlying, arguments); } }); @@ -262,7 +269,8 @@ module Playback { if (results.length === 0) { if (defaultValue !== undefined) { return defaultValue; - } else { + } + else { throw new Error("No matching result in log array for: " + JSON.stringify(expectedFields)); } } @@ -290,7 +298,8 @@ module Playback { // If we got here, we didn't find a match if (defaultValue === undefined) { throw new Error("No matching result in log array for path: " + expectedPath); - } else { + } + else { return defaultValue; } } @@ -308,7 +317,8 @@ module Playback { } if (pathEquivCache.hasOwnProperty(key)) { return pathEquivCache[key]; - } else { + } + else { return pathEquivCache[key] = check(); } } From 5b5d876cc215b4196fd8f2931bc0ec1a54c16a4e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 15 Sep 2015 17:47:50 -0700 Subject: [PATCH 7/7] more code review comments --- src/harness/rwcRunner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index c6637562ce5..1e81392049d 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -84,9 +84,9 @@ module RWC { } // Load the files - ts.forEach(fileNames, fileName => { + for (let fileName of fileNames) { inputFiles.push(getHarnessCompilerInputUnit(fileName)); - }); + } // Add files to compilation let isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath;