From dedb7fd0112c7e8b5952111bbd5ac304c6bb7f2e Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 27 Jan 2026 15:11:00 -0500 Subject: [PATCH 1/4] Support -v for version --- src/ts2famix-cli.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ts2famix-cli.ts b/src/ts2famix-cli.ts index 293883d7..382461c6 100644 --- a/src/ts2famix-cli.ts +++ b/src/ts2famix-cli.ts @@ -9,6 +9,8 @@ import { config } from "./analyze"; const argv = yargs .example(`ts2famix -i "path/to/project/**/*.ts" -o JSONModels/projectName.json`, 'Creates a JSON-format Famix model of typescript files.') .example(`ts2famix -i path/to/tsconfig.json -o JSONModels/projectName.json`, 'Creates a JSON-format model of a typescript project.') + .version() + .alias('v', 'version') .alias('i', 'input') .nargs('i', 1) .alias('o', 'output') From d48c71ee5334933bcff1fd1e8e63e0744ef5a473 Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 27 Jan 2026 15:12:44 -0500 Subject: [PATCH 2/4] Fix one-off error in anchor endPos --- src/famix_functions/EntityDictionary.ts | 4 ++-- test/alias.test.ts | 1 - test/functionWithVariables.test.ts | 4 ++-- test/sourceText.test.ts | 24 ++++++++++++------------ test/testUtils.ts | 4 ++-- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/famix_functions/EntityDictionary.ts b/src/famix_functions/EntityDictionary.ts index e631762f..41710dbc 100644 --- a/src/famix_functions/EntityDictionary.ts +++ b/src/famix_functions/EntityDictionary.ts @@ -96,7 +96,7 @@ export class EntityDictionary { // The +1 is because the source anchor (Pharo) is 1-based, but ts-morph is 0-based sourceAnchor.startPos = sourceStart + 1; - sourceAnchor.endPos = sourceEnd + 1; + sourceAnchor.endPos = sourceEnd; let fileName = node.getSourceFile().getFilePath() as string; if (fileName.startsWith("/")) { @@ -196,7 +196,7 @@ export class EntityDictionary { } // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based fmxIndexFileAnchor.startPos = sourceStart + 1; - fmxIndexFileAnchor.endPos = sourceEnd + 1; + fmxIndexFileAnchor.endPos = sourceEnd; // if (!(famixElement instanceof Famix.ImportClause || famixElement instanceof Famix.Access || famixElement instanceof Famix.Reference || famixElement instanceof Famix.Invocation || famixElement instanceof Famix.Inheritance) && !(famixElement instanceof Famix.Comment) && !(sourceElement instanceof CommentRange) && !(sourceElement instanceof Identifier) && !(sourceElement instanceof ImportSpecifier) && !(sourceElement instanceof ExpressionWithTypeArguments)) { // initFQN(sourceElement, famixElement); diff --git a/test/alias.test.ts b/test/alias.test.ts index 4d6c388b..720e0ffd 100644 --- a/test/alias.test.ts +++ b/test/alias.test.ts @@ -21,7 +21,6 @@ const arrayOfAliases = Array.from(setOfAliases); const arrayOfTypes = Array.from(fmxRep._getAllEntitiesWithType("Type") as Set); const theFirstAlias = arrayOfAliases[0]; const theFirstType = arrayOfTypes[0]; -const theFile = fmxRep._getFamixFile("alias.ts"); describe('Tests for alias', () => { diff --git a/test/functionWithVariables.test.ts b/test/functionWithVariables.test.ts index ed590bd9..7ff849ee 100644 --- a/test/functionWithVariables.test.ts +++ b/test/functionWithVariables.test.ts @@ -57,12 +57,12 @@ describe('Tests for function with variables', () => { let anchor = secondVariableComments[0]?.sourceAnchor as IndexedFileAnchor; expect(anchor?.fileName.endsWith("functionWithVariables.ts")).toBe(true); expect(project.getSourceFileOrThrow(anchor.fileName).getFullText().substring( - anchor.startPos - 1, anchor.endPos - 1)).toBe(`// comment 1`); + anchor.startPos - 1, anchor.endPos)).toBe(`// comment 1`); anchor = secondVariableComments[1]?.sourceAnchor as IndexedFileAnchor; expect(anchor?.fileName.endsWith("functionWithVariables.ts")).toBe(true); expect(project.getSourceFileOrThrow(anchor.fileName).getFullText().substring( - anchor.startPos - 1, anchor.endPos - 1)).toBe(`// comment 3`); + anchor.startPos - 1, anchor.endPos)).toBe(`// comment 3`); expect(secondVariableComments[0]?.container).toBe(secondVariable); expect(secondVariableComments[1]?.container).toBe(secondVariable); diff --git a/test/sourceText.test.ts b/test/sourceText.test.ts index 9fa86093..e569476e 100644 --- a/test/sourceText.test.ts +++ b/test/sourceText.test.ts @@ -32,11 +32,11 @@ describe('Tests for source text', () => { const sourceAnchor = theClass?.sourceAnchor as IndexedFileAnchor; // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(19 + 1); - expect(sourceAnchor.endPos).toBe(402 + 1); + expect(sourceAnchor.endPos).toBe(402); expect(sourceAnchor.fileName).toBe("test_src/simple.ts"); expect(project.getSourceFileOrThrow( sourceAnchor.fileName).getFullText().substring( - sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)) + sourceAnchor.startPos - 1, sourceAnchor.endPos)) .toBe( `export class A { /** @@ -55,11 +55,11 @@ describe('Tests for source text', () => { const sourceAnchor = theMethod.sourceAnchor as IndexedFileAnchor; // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(266 + 1); - expect(sourceAnchor.endPos).toBe(400 + 1); + expect(sourceAnchor.endPos).toBe(400); expect(sourceAnchor.fileName).toBe("test_src/simple.ts"); expect(project.getSourceFileOrThrow( sourceAnchor.fileName).getFullText().substring( - sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)) + sourceAnchor.startPos - 1, sourceAnchor.endPos)) .toBe(`public moveBack(numberOfSpaces: number) { let currentSquareIndex = this.board.indexOf(this.currentPlayer.currentSquare); }` @@ -73,11 +73,11 @@ describe('Tests for source text', () => { const sourceAnchor = theVariable.sourceAnchor as IndexedFileAnchor; // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(4 + 1); - expect(sourceAnchor.endPos).toBe(17 + 1); + expect(sourceAnchor.endPos).toBe(17); expect(sourceAnchor.fileName).toBe("test_src/simple.ts"); expect(project.getSourceFileOrThrow( sourceAnchor.fileName).getFullText().substring( - sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)) + sourceAnchor.startPos - 1, sourceAnchor.endPos)) .toBe("a: number = 1"); }); @@ -87,11 +87,11 @@ describe('Tests for source text', () => { const sourceAnchor = theVariable.sourceAnchor as IndexedFileAnchor; // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(320 + 1); - expect(sourceAnchor.endPos).toBe(393 + 1); + expect(sourceAnchor.endPos).toBe(393); expect(sourceAnchor.fileName).toBe("test_src/simple.ts"); expect(project.getSourceFileOrThrow( sourceAnchor.fileName).getFullText().substring( - sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)) + sourceAnchor.startPos - 1, sourceAnchor.endPos)) .toBe("currentSquareIndex = this.board.indexOf(this.currentPlayer.currentSquare)"); }); @@ -106,10 +106,10 @@ describe('Tests for source text', () => { expect(testSourceWithGraphemes.length).toBe(7); // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(4 + 1); - expect(sourceAnchor.endPos).toBe(4 + testSourceWithGraphemes.length + 1); + expect(sourceAnchor.endPos).toBe(4 + testSourceWithGraphemes.length); expect(sourceAnchor.fileName).toBe("test_src/a-b.ts"); const sourceFileTextWithGraphemes = splitter.splitGraphemes(project.getSourceFileOrThrow(sourceAnchor.fileName).getFullText()); - expect(sourceFileTextWithGraphemes.slice(sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)).toEqual(testSourceWithGraphemes); + expect(sourceFileTextWithGraphemes.slice(sourceAnchor.startPos - 1, sourceAnchor.endPos)).toEqual(testSourceWithGraphemes); }); it("should have variable 'd' with the proper source text", () => { @@ -117,10 +117,10 @@ describe('Tests for source text', () => { const sourceAnchor = theVariable.sourceAnchor as IndexedFileAnchor; // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based expect(sourceAnchor.startPos).toBe(13 + 1); - expect(sourceAnchor.endPos).toBe(18 + 1); + expect(sourceAnchor.endPos).toBe(18); expect(sourceAnchor.fileName).toBe("test_src/a-b.ts"); const sourceFileTextWithGraphemes = splitter.splitGraphemes(project.getSourceFileOrThrow(sourceAnchor.fileName).getFullText()); const testSourceWithGraphemes = splitter.splitGraphemes('d = 5'); - expect(sourceFileTextWithGraphemes.slice(sourceAnchor.startPos - 1, sourceAnchor.endPos - 1)).toEqual(testSourceWithGraphemes); }); + expect(sourceFileTextWithGraphemes.slice(sourceAnchor.startPos - 1, sourceAnchor.endPos)).toEqual(testSourceWithGraphemes); }); }); diff --git a/test/testUtils.ts b/test/testUtils.ts index 998cce1e..787767f8 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -16,7 +16,7 @@ function getIndexedFileAnchorFromComment(comment: Comment) { } function getCommentFromAnchor(anchor: IndexedFileAnchor, project: Project) { - return project.getSourceFileOrThrow(anchor.fileName).getFullText().substring(anchor.startPos - 1, anchor.endPos - 1); + return project.getSourceFileOrThrow(anchor.fileName).getFullText().substring(anchor.startPos - 1, anchor.endPos); } export function getCommentTextFromCommentViaAnchor(comment: Comment, project: Project) { @@ -24,5 +24,5 @@ export function getCommentTextFromCommentViaAnchor(comment: Comment, project: Pr } export function getTextFromAnchor(anchor: IndexedFileAnchor, project: Project) { - return project.getSourceFileOrThrow(anchor.fileName).getFullText().substring(anchor.startPos - 1, anchor.endPos - 1); + return project.getSourceFileOrThrow(anchor.fileName).getFullText().substring(anchor.startPos - 1, anchor.endPos); } From c2a38d9cc5db5ec570c448f49e0cb943abe1021f Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 27 Jan 2026 16:41:04 -0500 Subject: [PATCH 3/4] npm audit fix, Fixes 3.0.x #88 --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1cc3bedf..3c34cd4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2703,9 +2703,9 @@ } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4684,9 +4684,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.memoize": { From 32351d417742cfe2ff4e38f49944b82743fa092f Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 27 Jan 2026 16:42:57 -0500 Subject: [PATCH 4/4] Fixes endPos and adds -v command line --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3c34cd4d..a830f707 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ts2famix", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ts2famix", - "version": "3.0.0", + "version": "3.1.0", "license": "MIT", "dependencies": { "grapheme-splitter": "^1.0.4", diff --git a/package.json b/package.json index b795fe77..cc1f065e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ts2famix", - "version": "3.0.0", + "version": "3.1.0", "description": "A TypeScript to JSON importer for Moose.", "main": "dist/ts2famix-cli.js", "scripts": {