fcis 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/.plans/001-fcis-analyzer.md +832 -0
  2. package/.plans/002-fcis-analyzer-improvements.md +205 -0
  3. package/README.md +272 -0
  4. package/TECHNICAL.md +386 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +1836 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/index.d.ts +709 -0
  9. package/dist/index.js +1845 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +47 -0
  12. package/pnpm-workspace.yaml +0 -0
  13. package/src/analyzer.ts +266 -0
  14. package/src/classification/classifier.ts +156 -0
  15. package/src/classification/derive-status.ts +171 -0
  16. package/src/classification/quality-scorer.ts +481 -0
  17. package/src/cli.ts +286 -0
  18. package/src/detection/detect-markers.ts +480 -0
  19. package/src/detection/markers.ts +332 -0
  20. package/src/extraction/extract-functions.ts +570 -0
  21. package/src/extraction/extractor.ts +188 -0
  22. package/src/index.ts +111 -0
  23. package/src/reporting/report-console.ts +416 -0
  24. package/src/reporting/report-json.ts +232 -0
  25. package/src/scoring/scorer.ts +504 -0
  26. package/src/types.ts +248 -0
  27. package/tests/classifier.test.ts +480 -0
  28. package/tests/derive-status.test.ts +464 -0
  29. package/tests/detect-markers.test.ts +639 -0
  30. package/tests/extractor.test.ts +155 -0
  31. package/tests/integration.test.ts +706 -0
  32. package/tests/quality-scorer.test.ts +650 -0
  33. package/tests/scorer.test.ts +768 -0
  34. package/tsconfig.json +34 -0
  35. package/tsup.config.ts +17 -0
  36. package/vendor/ts-morph/.editorconfig +10 -0
  37. package/vendor/ts-morph/.gitattributes +11 -0
  38. package/vendor/ts-morph/.github/CODE_OF_CONDUCT.md +77 -0
  39. package/vendor/ts-morph/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
  40. package/vendor/ts-morph/.github/ISSUE_TEMPLATE/custom.md +4 -0
  41. package/vendor/ts-morph/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
  42. package/vendor/ts-morph/.github/workflows/ci.yml +50 -0
  43. package/vendor/ts-morph/.github/workflows/publish.yml +53 -0
  44. package/vendor/ts-morph/.vscode/settings.json +10 -0
  45. package/vendor/ts-morph/CONTRIBUTING.md +23 -0
  46. package/vendor/ts-morph/DEVELOPMENT.md +32 -0
  47. package/vendor/ts-morph/LICENSE +21 -0
  48. package/vendor/ts-morph/deno.json +8 -0
  49. package/vendor/ts-morph/deno.lock +1233 -0
  50. package/vendor/ts-morph/docs/CNAME +1 -0
  51. package/vendor/ts-morph/docs/Gemfile +2 -0
  52. package/vendor/ts-morph/docs/_config.yml +5 -0
  53. package/vendor/ts-morph/docs/_layouts/default.html +159 -0
  54. package/vendor/ts-morph/docs/_script-templates/main.ts +116 -0
  55. package/vendor/ts-morph/docs/assets/css/style.scss +212 -0
  56. package/vendor/ts-morph/docs/details/ambient.md +38 -0
  57. package/vendor/ts-morph/docs/details/async.md +31 -0
  58. package/vendor/ts-morph/docs/details/classes.md +314 -0
  59. package/vendor/ts-morph/docs/details/comment-ranges.md +7 -0
  60. package/vendor/ts-morph/docs/details/comments.md +122 -0
  61. package/vendor/ts-morph/docs/details/decorators.md +119 -0
  62. package/vendor/ts-morph/docs/details/documentation.md +73 -0
  63. package/vendor/ts-morph/docs/details/enums.md +117 -0
  64. package/vendor/ts-morph/docs/details/exports.md +308 -0
  65. package/vendor/ts-morph/docs/details/expressions.md +46 -0
  66. package/vendor/ts-morph/docs/details/functions.md +150 -0
  67. package/vendor/ts-morph/docs/details/generators.md +27 -0
  68. package/vendor/ts-morph/docs/details/identifiers.md +79 -0
  69. package/vendor/ts-morph/docs/details/imports.md +191 -0
  70. package/vendor/ts-morph/docs/details/index.md +52 -0
  71. package/vendor/ts-morph/docs/details/initializers.md +40 -0
  72. package/vendor/ts-morph/docs/details/interfaces.md +218 -0
  73. package/vendor/ts-morph/docs/details/literals.md +20 -0
  74. package/vendor/ts-morph/docs/details/modifiers.md +38 -0
  75. package/vendor/ts-morph/docs/details/modules.md +113 -0
  76. package/vendor/ts-morph/docs/details/namespaces.md +7 -0
  77. package/vendor/ts-morph/docs/details/object-literal-expressions.md +106 -0
  78. package/vendor/ts-morph/docs/details/parameters.md +64 -0
  79. package/vendor/ts-morph/docs/details/signatures.md +41 -0
  80. package/vendor/ts-morph/docs/details/source-files.md +292 -0
  81. package/vendor/ts-morph/docs/details/type-aliases.md +34 -0
  82. package/vendor/ts-morph/docs/details/type-parameters.md +72 -0
  83. package/vendor/ts-morph/docs/details/types.md +254 -0
  84. package/vendor/ts-morph/docs/details/variables.md +110 -0
  85. package/vendor/ts-morph/docs/emitting.md +151 -0
  86. package/vendor/ts-morph/docs/index.md +25 -0
  87. package/vendor/ts-morph/docs/manipulation/code-writer.md +20 -0
  88. package/vendor/ts-morph/docs/manipulation/formatting.md +76 -0
  89. package/vendor/ts-morph/docs/manipulation/index.md +136 -0
  90. package/vendor/ts-morph/docs/manipulation/order.md +14 -0
  91. package/vendor/ts-morph/docs/manipulation/performance.md +222 -0
  92. package/vendor/ts-morph/docs/manipulation/removing.md +31 -0
  93. package/vendor/ts-morph/docs/manipulation/renaming.md +106 -0
  94. package/vendor/ts-morph/docs/manipulation/settings.md +76 -0
  95. package/vendor/ts-morph/docs/manipulation/structures.md +117 -0
  96. package/vendor/ts-morph/docs/manipulation/transforms.md +84 -0
  97. package/vendor/ts-morph/docs/metrics/performance.json +4 -0
  98. package/vendor/ts-morph/docs/navigation/ambient-modules.md +22 -0
  99. package/vendor/ts-morph/docs/navigation/compiler-nodes.md +82 -0
  100. package/vendor/ts-morph/docs/navigation/directories.md +287 -0
  101. package/vendor/ts-morph/docs/navigation/example.md +50 -0
  102. package/vendor/ts-morph/docs/navigation/finding-references.md +53 -0
  103. package/vendor/ts-morph/docs/navigation/getting-source-files.md +59 -0
  104. package/vendor/ts-morph/docs/navigation/images/getChildrenVsForEachChild.gif +0 -0
  105. package/vendor/ts-morph/docs/navigation/index.md +94 -0
  106. package/vendor/ts-morph/docs/navigation/language-service.md +23 -0
  107. package/vendor/ts-morph/docs/navigation/program.md +25 -0
  108. package/vendor/ts-morph/docs/navigation/type-checker.md +33 -0
  109. package/vendor/ts-morph/docs/setup/adding-source-files.md +145 -0
  110. package/vendor/ts-morph/docs/setup/ast-viewers.md +46 -0
  111. package/vendor/ts-morph/docs/setup/diagnostics.md +109 -0
  112. package/vendor/ts-morph/docs/setup/file-system.md +106 -0
  113. package/vendor/ts-morph/docs/setup/images/atom-ast.png +0 -0
  114. package/vendor/ts-morph/docs/setup/images/atom-ast_small.png +0 -0
  115. package/vendor/ts-morph/docs/setup/images/atom-command-palette.png +0 -0
  116. package/vendor/ts-morph/docs/setup/images/atom-file.png +0 -0
  117. package/vendor/ts-morph/docs/setup/images/ts-ast-viewer.png +0 -0
  118. package/vendor/ts-morph/docs/setup/index.md +94 -0
  119. package/vendor/ts-morph/docs/utilities.md +55 -0
  120. package/vendor/ts-morph/dprint.json +23 -0
  121. package/vendor/ts-morph/package.json +30 -0
  122. package/vendor/ts-morph/packages/bootstrap/LICENSE +21 -0
  123. package/vendor/ts-morph/packages/bootstrap/lib/ts-morph-bootstrap.d.ts +397 -0
  124. package/vendor/ts-morph/packages/bootstrap/package.json +46 -0
  125. package/vendor/ts-morph/packages/bootstrap/readme.md +200 -0
  126. package/vendor/ts-morph/packages/common/LICENSE +21 -0
  127. package/vendor/ts-morph/packages/common/lib/ts-morph-common.d.ts +1082 -0
  128. package/vendor/ts-morph/packages/common/lib/typescript.d.ts +11439 -0
  129. package/vendor/ts-morph/packages/common/package.json +65 -0
  130. package/vendor/ts-morph/packages/common/readme.md +5 -0
  131. package/vendor/ts-morph/packages/scripts/changeTypeScriptVersion.ts +28 -0
  132. package/vendor/ts-morph/packages/scripts/createDeclarationProject.ts +47 -0
  133. package/vendor/ts-morph/packages/scripts/deps.ts +2 -0
  134. package/vendor/ts-morph/packages/scripts/execScript.ts +31 -0
  135. package/vendor/ts-morph/packages/scripts/folders.ts +11 -0
  136. package/vendor/ts-morph/packages/scripts/getDevCompilerVersions.ts +19 -0
  137. package/vendor/ts-morph/packages/scripts/mod.ts +7 -0
  138. package/vendor/ts-morph/packages/scripts/utils/Memoize.ts +36 -0
  139. package/vendor/ts-morph/packages/scripts/utils/forEachTypeText.ts +23 -0
  140. package/vendor/ts-morph/packages/scripts/utils/makeConstructorsPrivate.ts +26 -0
  141. package/vendor/ts-morph/packages/scripts/utils/mod.ts +4 -0
  142. package/vendor/ts-morph/packages/scripts/utils/printDiagnostics.ts +10 -0
  143. package/vendor/ts-morph/packages/ts-morph/LICENSE +21 -0
  144. package/vendor/ts-morph/packages/ts-morph/lib/ts-morph.d.ts +11198 -0
  145. package/vendor/ts-morph/packages/ts-morph/package.json +78 -0
  146. package/vendor/ts-morph/packages/ts-morph/readme.md +111 -0
  147. package/vendor/ts-morph/readme.md +14 -0
  148. package/vendor/ts-morph/rfcs/README.md +13 -0
  149. package/vendor/ts-morph/rfcs/RFC-0001 - Inserting Into Statements Handling Comments.md +181 -0
  150. package/vendor/ts-morph/tsconfig.common.json +17 -0
  151. package/vitest.config.ts +16 -0
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: Manipulating Source Files
3
+ ---
4
+
5
+ ## Manipulating Source Files
6
+
7
+ Most information about manipulation can be found in the [Details](../details) section. This section only contains general information about manipulation.
8
+
9
+ ### Saving Changes
10
+
11
+ All moves, copies, and deletes won't be propagated to the underlying file system until `save()` is called on the main `project` object.
12
+
13
+ ```ts
14
+ import { Project } from "ts-morph";
15
+
16
+ const project = new Project();
17
+
18
+ // ...lots of code here that manipulates, copies, moves, and deletes files...
19
+
20
+ // when you're all done, call this and it will save everything to the file system
21
+ await project.save();
22
+ ```
23
+
24
+ The above is recommended because it means if your code errors halfway through, the files won't be in a halfway state. However, there's always a way to save, move, copy, and delete while immediately having these changes happen on the underlying file system. For example:
25
+
26
+ ```ts
27
+ // or use the synchronous alternatives (ex. saveSync())
28
+ await sourceFile.save();
29
+ await sourceFile.deleteImmediately();
30
+ await sourceFile.copyImmediately("copiedFile.ts");
31
+ await sourceFile.moveImmediately("movedFile.ts");
32
+
33
+ await directory.save();
34
+ await directory.deleteImmediately();
35
+ await directory.copyImmediately("CopiedDir");
36
+ await directory.moveImmediately("MovedDir");
37
+ ```
38
+
39
+ ### Replacing any node with new text
40
+
41
+ Use the `.replaceWithText(...)` method that exists on any node.
42
+
43
+ This will replace the text from the `Node#getStart(true)` position (start position with js docs) to `Node#getEnd()`. Use `Node#getText(true)` to get all the text that will be replaced.
44
+
45
+ #### Example
46
+
47
+ Given the following code:
48
+
49
+ ```ts setup: let Some: any;
50
+ let myVariable = Some.Property.Access.Expression;
51
+ ```
52
+
53
+ You can replace the property access expression with new text by doing the following:
54
+
55
+ ```ts
56
+ const originalInitializer = sourceFile.getVariableDeclarations()[0].getInitializerOrThrow();
57
+ const newInitializer = originalInitializer.replaceWithText("MyReference");
58
+ ```
59
+
60
+ That will make the source file hold the following text:
61
+
62
+ ```ts setup: let MyReference: any;
63
+ let myVariable = MyReference;
64
+ ```
65
+
66
+ Note that `originalInitializer` will be forgotten after calling `.replaceWithText(...)` on it—an error will be thrown if you try to use it.
67
+ You will have to use the new node returned by that method.
68
+
69
+ ### Adding, inserting, and removing statements
70
+
71
+ Statements can be added, inserted, or removed from nodes with a body (ex. functions, methods, namespaces, source files).
72
+
73
+ ```ts
74
+ // add statements
75
+ const statements = sourceFile.addStatements("console.log(5);\nconsole.log(6);");
76
+ // insert statements (index is the child index to insert at)
77
+ const statements = sourceFile.insertStatements(3, "console.log(5);\nconsole.log(6);");
78
+ // remove statements
79
+ sourceFile.removeStatements([1, 3]); // removes statements from index 1 to 3
80
+ sourceFile.removeStatement(1); // removes statement at index 1
81
+ ```
82
+
83
+ When adding or inserting, you can also write using a [code writer](code-writer):
84
+
85
+ ```ts
86
+ functionDeclaration.addStatements(writer => {
87
+ writer.write("if (true)").block(() => {
88
+ writer.write("something;");
89
+ });
90
+ });
91
+ ```
92
+
93
+ ### Inserting, replacing, and removing any text
94
+
95
+ In some scenarios, a simple to use API might not have been implemented. If you find that's the case, open an issue on GitHub.
96
+
97
+ In the meantime, you can insert, replace, and remove text using the following methods, but _generally you will want to avoid using these if possible_:
98
+
99
+ ```ts
100
+ // insert text
101
+ sourceFile.insertText(0, writer => writer.writeLine("// some comment")); // or provide a string
102
+ // replace text
103
+ sourceFile.replaceText([3, 7], "a"); // "// a comment\n"
104
+ // remove text
105
+ sourceFile.removeText(sourceFile.getPos(), sourceFile.getEnd());
106
+ ```
107
+
108
+ These methods are also available on any node that has a body (functions, classes, enums, etc.)
109
+
110
+ #### **Warning**
111
+
112
+ If you use `insertText`, `replaceText`, or `removeText`, all previously navigated descendants of the node will be forgotten and not be available for use—an error will be thrown
113
+ if you try to use them. You will have to renavigate to those nodes.
114
+
115
+ For example:
116
+
117
+ ```ts
118
+ let classDeclaration = sourceFile.addClass({ name: "MyClass" });
119
+ sourceFile.insertText(0, "// some comment\n");
120
+
121
+ // this will throw...
122
+ classDeclaration.getInstanceProperties();
123
+
124
+ // you'll need to get the reference again:
125
+ classDeclaration = sourceFile.getClass("MyClass")!;
126
+ ```
127
+
128
+ ## Code Fixes
129
+
130
+ There are a variety of useful code fixes and refactors such as:
131
+
132
+ - `SourceFile#organizeImports()`
133
+ - `SourceFile#fixMissingImports()`
134
+ - `SourceFile#fixUnusedIdentifiers()`
135
+
136
+ Check more details on the [source files details page](../details/source-files).
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Order
3
+ ---
4
+
5
+ ## Order
6
+
7
+ Change the order of certain nodes using the `.setOrder(newIndex: number)` method.
8
+
9
+ ```ts
10
+ const interfaceDeclaration = sourceFile.getInterfaceOrThrow("MyInterface");
11
+ interfaceDeclaration.setOrder(2);
12
+ ```
13
+
14
+ Notice: Right now this is not supported on comma separated nodes. See [Issue #44](https://github.com/dsherret/ts-morph/issues/44) for more information.
@@ -0,0 +1,222 @@
1
+ ---
2
+ title: Performance
3
+ ---
4
+
5
+ ## Performance
6
+
7
+ There's a lot of opportunity for performance improvements. The library originally started off favouring correctness, but it's now starting to switch to improving performance.
8
+
9
+ [View Issues](https://github.com/dsherret/ts-morph/labels/performance)
10
+
11
+ ### Manipulations are slow...
12
+
13
+ Right now with every manipulation the following occurs:
14
+
15
+ 1. The file text is updated.
16
+ 2. The new text is parsed and a new AST is created using the compiler API.
17
+ 3. The previously wrapped nodes are backfilled with new compiler nodes.
18
+
19
+ This might not be too bad when working with small to medium sized files, but large files may take a bit of time. If you find it's too slow, then I recommend reading the performance tips below.
20
+
21
+ Note: I'm working on eliminating the need to do a complete parse of the source file between manipulations. Once implemented these performance tips won't be necessary.
22
+
23
+ ### Performance Tip: Work With Structures Instead
24
+
25
+ Structures are simplified ASTs. You can get a huge performance improvement by working with structures as much as possible. This is especially useful to do if you are code generating.
26
+
27
+ Example:
28
+
29
+ ```ts
30
+ // this code will get a structure from declarations.ts, make all the descendants not be exported,
31
+ // then create a new file called private.ts from that structure
32
+ import { forEachStructureChild, SourceFileStructure, StructureKind, Structures, Structures } from "ts-morph";
33
+
34
+ const project = new Project({ tsConfigFilePath: "tsconfig.json" });
35
+ const classesFile = project.getSourceFileOrThrow("declarations.ts");
36
+ const classesFileStructure = classesFile.getStructure();
37
+
38
+ removeExports(classesFileStructure);
39
+
40
+ project.createSourceFile("private.ts", classesFileStructure);
41
+
42
+ function removeExports(structure: Structures) {
43
+ forEachStructureChild(structure, removeExports);
44
+
45
+ if (Structure.isExportable(structure))
46
+ structure.isExported = false;
47
+ }
48
+ ```
49
+
50
+ Read more in [structures](structures.md).
51
+
52
+ ### Performance Tip: Batch operations
53
+
54
+ You can reduce the amount of parsing that needs to happen by batching operations.
55
+
56
+ For example, instead of writing code like this:
57
+
58
+ ```ts setup: const classStructures: ClassDeclarationStructure[];
59
+ for (const classStructure of classStructures)
60
+ sourceFile.addClass(classStructure);
61
+ ```
62
+
63
+ Write this instead:
64
+
65
+ ```ts setup: const classStructures: ClassDeclarationStructure[];
66
+ sourceFile.addClasses(classStructures);
67
+ ```
68
+
69
+ ### Performance Tip: Analyze then Manipulate
70
+
71
+ If the code analysis is using types, symbols type checker, or program, then a large performance improvement can be gained by doing an initial analysis of the code first, then afterwards carrying out the manipulations.
72
+
73
+ For example, given the following code:
74
+
75
+ ```ts setup: const sourceFiles: SourceFile[]; const someCheckOnSymbol: any;
76
+ for (const sourceFile of sourceFiles) {
77
+ for (const classDec of sourceFile.getClasses()) {
78
+ if (someCheckOnSymbol(classDec.getSymbolOrThrow()))
79
+ classDec.remove();
80
+ }
81
+ }
82
+ ```
83
+
84
+ Write it this way instead:
85
+
86
+ ```ts setup: const sourceFiles: SourceFile[]; const someCheckOnSymbol: any;
87
+ for (const classDec of getClassesToRemove())
88
+ classDec.remove();
89
+
90
+ function getClassesToRemove() {
91
+ const classesToRemove: ClassDeclaration[] = [];
92
+
93
+ for (const sourceFile of sourceFiles) {
94
+ for (const classDec of sourceFile.getClasses()) {
95
+ if (someCheckOnSymbol(classDec.getSymbolOrThrow()))
96
+ classesToRemove.push(classDec);
97
+ }
98
+ }
99
+
100
+ return classesToRemove;
101
+ }
102
+ ```
103
+
104
+ This is because the program is reset between manipulations.
105
+
106
+ ### Tracking Nodes - Overview
107
+
108
+ This library makes manipulations easy for you by keeping track of how the underlying syntax tree changes between manipulations.
109
+
110
+ Behind the scenes, when you manipulate the AST:
111
+
112
+ 1. A new source file is created using the TypeScript compiler.
113
+ 2. The previously navigated nodes have their underlying compiler nodes replaced with the new compiler nodes.
114
+
115
+ It's why you can do this:
116
+
117
+ ```ts
118
+ // sourcefile contains: interface Person { name: string; }
119
+ const personInterface = sourceFile.getInterfaceOrThrow("Person");
120
+ const nameProperty = personInterface.getPropertyOrThrow("name");
121
+ nameProperty.setType("number");
122
+ nameProperty.getText(); // "name: number;"
123
+ ```
124
+
125
+ Instead of having to renavigate the tree after each manipulation:
126
+
127
+ ```ts
128
+ // thankfully the library does not work this way
129
+ let personInterface = sourceFile.getInterfaceOrThrow("Person");
130
+ let nameProperty = personInterface.getPropertyOrThrow("name");
131
+ nameProperty.setType("number");
132
+ nameProperty.getText(); // "name: string;"
133
+ personInterface = sourceFile.getInterfaceOrThrow("Person");
134
+ nameProperty = personInterface.getPropertyOrThrow("name");
135
+ nameProperty.getText(); // "name: number;"
136
+ ```
137
+
138
+ When thinking about performance, the key point here is that if you have a lot of previously navigated nodes and a very large file, then manipulation might start to become sluggish.
139
+
140
+ #### Forgetting Nodes (Advanced)
141
+
142
+ The main way to improve performance when manipulating, is to "forget" a node when you're done with it.
143
+
144
+ ```ts setup: let personInterface: InterfaceDeclaration;
145
+ personInterface.forget();
146
+
147
+ // or to only forget a node's descendants that are currently in the wrapped cache
148
+ sourceFile.forgetDescendants();
149
+ ```
150
+
151
+ That will stop tracking the node and all its previously navigated descendants (ex. in this case, `nameProperty` as well).
152
+ It won't be updated when manipulation happens again. Note that after doing this, the node will throw an error if one of its properties or methods is accessed.
153
+
154
+ #### Forget Blocks (Advanced)
155
+
156
+ It's possible to make sure all created nodes within a block are forgotten:
157
+
158
+ ```ts
159
+ import { ClassDeclaration, InterfaceDeclaration, ModuleDeclaration, Project } from "ts-morph";
160
+
161
+ const project = new Project();
162
+ const text = "namespace Namespace { interface Interface {} class Class {} }";
163
+ const sourceFile = project.createSourceFile("file.ts", text);
164
+
165
+ let moduleDeclaration: ModuleDeclaration;
166
+ let interfaceDeclaration: InterfaceDeclaration;
167
+ let classDeclaration: ClassDeclaration;
168
+
169
+ project.forgetNodesCreatedInBlock(remember => {
170
+ moduleDeclaration = sourceFile.getModuleOrThrow("Namespace");
171
+ interfaceDeclaration = moduleDeclaration.getInterfaceOrThrow("Interface");
172
+ classDeclaration = moduleDeclaration.getClassOrThrow("Class");
173
+
174
+ // you can mark nodes to remember outside the scope of this block...
175
+ // this will remember the specified node and all its ancestors
176
+ remember(interfaceDeclaration); // or pass in multiple nodes
177
+ });
178
+
179
+ moduleDeclaration.getText(); // ok, child was implicitly marked to remember
180
+ interfaceDeclaration.getText(); // ok, was explicitly marked to remember
181
+ classDeclaration.getText(); // throws, was forgotten
182
+
183
+ // alternatively, return the node to remember it
184
+ const node = project.forgetNodesCreatedInBlock(() => {
185
+ const classDec = sourceFile.getClassOrThrow("MyClass");
186
+ // ...do a lot of stuff...
187
+ return classDec;
188
+ });
189
+
190
+ node.getText(); // ok
191
+ ```
192
+
193
+ Also, do not be concerned about nesting forget blocks. That is perfectly fine to do:
194
+
195
+ ```ts
196
+ project.forgetNodesCreatedInBlock(() => {
197
+ moduleDeclaration = sourceFile.getModuleOrThrow("Namespace");
198
+ interfaceDeclaration = moduleDeclaration.getInterfaceOrThrow("Interface");
199
+
200
+ project.forgetNodesCreatedInBlock(remember => {
201
+ classDeclaration = moduleDeclaration.getClassOrThrow("Class");
202
+ remember(moduleDeclaration);
203
+ });
204
+
205
+ classDeclaration.getText(); // throws, was forgotten outside the block above
206
+ interfaceDeclaration.getText(); // ok, hasn't been forgotten yet
207
+ });
208
+
209
+ moduleDeclaration.getText(); // ok, was marked to remember in one of the blocks
210
+ interfaceDeclaration.getText(); // throws, was forgotten
211
+ classDeclaration.getText(); // throws, was forgotten
212
+ ```
213
+
214
+ ##### Async
215
+
216
+ This method supports async and await:
217
+
218
+ ```ts
219
+ await project.forgetNodesCreatedInBlock(async remember => {
220
+ // do stuff
221
+ });
222
+ ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Removing
3
+ ---
4
+
5
+ ## Removing
6
+
7
+ Given the source file for following code:
8
+
9
+ ```ts
10
+ enum MyEnum {
11
+ myMember,
12
+ }
13
+ ```
14
+
15
+ Removing can be done as follows:
16
+
17
+ ```ts
18
+ const member = sourceFile.getEnum("MyEnum")!.getMember("myMember")!;
19
+ member.remove();
20
+ ```
21
+
22
+ So the file above would now contain the following code:
23
+
24
+ ```ts
25
+ enum MyEnum {
26
+ }
27
+ ```
28
+
29
+ ### Support
30
+
31
+ Currently removing is implemented individually for each kind of node. In general this will work for many kind of nodes, including methods, properties, constructors, parmeters, statements, declarations. Nevertheless, if you find that `remove()` method is not implemented for a particular kind of Node, please open an issue on github.
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: Renaming
3
+ ---
4
+
5
+ ## Renaming
6
+
7
+ Given the source file for following code:
8
+
9
+ ```ts
10
+ enum MyEnum {
11
+ myMember,
12
+ }
13
+ const myVar = MyEnum.myMember;
14
+ ```
15
+
16
+ Renaming can be done as follows:
17
+
18
+ ```ts
19
+ const myEnum = sourceFile.getEnum("MyEnum")!;
20
+ myEnum.rename("NewEnum");
21
+ ```
22
+
23
+ Which will rename all usages of `MyEnum` to `NewEnum` across _all_ files.
24
+
25
+ So the file above would now contain the following code:
26
+
27
+ ```ts
28
+ enum NewEnum {
29
+ myMember,
30
+ }
31
+
32
+ const myVar = NewEnum.myMember;
33
+ ```
34
+
35
+ ### Renaming in comments and strings
36
+
37
+ Set the `renameInComments` and `renameInStrings` options to `true` (they are `false` by default):
38
+
39
+ ```ts setup: let myEnum: EnumDeclaration;
40
+ myEnum.rename("SomeOtherName", {
41
+ renameInComments: true,
42
+ renameInStrings: true,
43
+ });
44
+ ```
45
+
46
+ ### Renaming with prefix and suffix text
47
+
48
+ **Note:** This feature is only supported when using TypeScript 3.4+
49
+
50
+ By default, renames will not change shorthand property assignments or add aliases to import & export specifiers.
51
+
52
+ For example, renaming the `a` variable declaration to `b`...
53
+
54
+ ```ts
55
+ const a = 5;
56
+ const x = { a };
57
+
58
+ export { a };
59
+ ```
60
+
61
+ ...will do the following:
62
+
63
+ ```ts
64
+ const b = 5;
65
+ const x = { b };
66
+
67
+ export { b };
68
+ ```
69
+
70
+ This behaviour can be changed by enabling the `usePrefixAndSuffixText` setting, which will do the following:
71
+
72
+ ```ts
73
+ const b = 5;
74
+ const x = { a: b };
75
+
76
+ export { b as a };
77
+ ```
78
+
79
+ This behaviour change can be specified when renaming:
80
+
81
+ ```ts setup: let varA: VariableDeclaration;
82
+ varA.rename("SomeOtherName", {
83
+ usePrefixAndSuffixText: true,
84
+ });
85
+ ```
86
+
87
+ Or globally:
88
+
89
+ ```ts
90
+ const project = new Project({
91
+ manipulationSettings: {
92
+ usePrefixAndSuffixTextForRename: true,
93
+ },
94
+ });
95
+ // or
96
+ project.manipulationSettings.set({
97
+ usePrefixAndSuffixTextForRename: true,
98
+ });
99
+ ```
100
+
101
+ ### Renaming Files or Directories
102
+
103
+ See:
104
+
105
+ - [Moving Files](../details/source-files#move)
106
+ - [Moving Directories](../navigation/directories#moving)
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Manipulation Settings
3
+ ---
4
+
5
+ ## Manipulation Settings
6
+
7
+ The manipulation settings can be set when creating the main `Project` object:
8
+
9
+ ```ts
10
+ import { IndentationText, NewLineKind, Project, QuoteKind } from "ts-morph";
11
+
12
+ const project = new Project({
13
+ // these are the defaults
14
+ manipulationSettings: {
15
+ // TwoSpaces, FourSpaces, EightSpaces, or Tab
16
+ indentationText: IndentationText.FourSpaces,
17
+ // LineFeed or CarriageReturnLineFeed
18
+ newLineKind: NewLineKind.LineFeed,
19
+ // Single or Double
20
+ quoteKind: QuoteKind.Double,
21
+ // Whether to change shorthand property assignments to property assignments
22
+ // and add aliases to import & export specifiers (see more information in
23
+ // the renaming section of the documentation).
24
+ usePrefixAndSuffixTextForRename: false,
25
+ // Whether to use trailing commas in multi-line scenarios where trailing
26
+ // commas would be used.
27
+ useTrailingCommas: false,
28
+ },
29
+ });
30
+ ```
31
+
32
+ You can only provide a partial of these settings if you wish:
33
+
34
+ ```ts
35
+ const project = new Project({
36
+ manipulationSettings: { indentationText: IndentationText.TwoSpaces },
37
+ });
38
+ ```
39
+
40
+ ### Details
41
+
42
+ Get more details about the settings by looking at the `manipulationSettings` property on the main `Project` object:
43
+
44
+ ```ts
45
+ project.manipulationSettings.getIndentationText();
46
+ project.manipulationSettings.getNewLineKind();
47
+ project.manipulationSettings.getQuoteKind();
48
+ project.manipulationSettings.getUsePrefixAndSuffixTextForRename();
49
+ ```
50
+
51
+ ### Updating
52
+
53
+ You can update these settings later if you wish by using the `set` method:
54
+
55
+ ```ts
56
+ // set only one
57
+ project.manipulationSettings.set({ quoteKind: QuoteKind.Single });
58
+
59
+ // or multiple
60
+ project.manipulationSettings.set({
61
+ quoteKind: QuoteKind.Single,
62
+ indentationText: IndentationText.TwoSpaces,
63
+ });
64
+ ```
65
+
66
+ ### Formatting
67
+
68
+ There are some additional manipulation settings that are taken from the `ts.FormatCodeSettings`.
69
+ They will slowly be supported and added to the manipulation settings. For example:
70
+
71
+ ```ts
72
+ project.manipulationSettings.set({
73
+ // only one for now... will add more in the future
74
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: false, // default: true
75
+ });
76
+ ```
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: Structures
3
+ ---
4
+
5
+ ## Structures
6
+
7
+ Simplified AST representations called _structures_ can be retreived from and used to set many `Node` objects.
8
+
9
+ ### Getting structure
10
+
11
+ To get the structure of a node, call `node.getStructure()`.
12
+
13
+ ```ts
14
+ // example with a class declaration, but this also works on interfaces, enums, and many other nodes.
15
+ const classStructure = classDeclaration.getStructure(); // returns: ClassDeclarationStructure
16
+ ```
17
+
18
+ In the example above, a class declaration like the following...
19
+
20
+ ```ts
21
+ export class MyClass {
22
+ myProp = 5;
23
+ }
24
+ ```
25
+
26
+ ...would return the following structure object similar to the following:
27
+
28
+ ```js
29
+ {
30
+ isAbstract: false,
31
+ isExported: true,
32
+ name: "MyClass",
33
+ typeParameters: [],
34
+ constructors: [],
35
+ properties: [{
36
+ name: "myProp",
37
+ initializer: "5",
38
+ type: undefined,
39
+ isReadonly: false,
40
+ isStatic: false
41
+ }],
42
+ methods: []
43
+ }
44
+ ```
45
+
46
+ ### Setting with structure
47
+
48
+ It's also possible to set the structure of a node with an existing structure:
49
+
50
+ ```ts setup: const classStructure = {};
51
+ classDeclaration.set(classStructure);
52
+ // sets the name
53
+ classDeclaration.set({ name: "NewName" });
54
+ // sets the properties
55
+ classDeclaration.set({ properties: [{ name: "newProperty" }] });
56
+ ```
57
+
58
+ Or you can use the `addX` or `insertX` methods with a structure:
59
+
60
+ ```ts
61
+ sourceFile.addClass({ name: "NewClass", ...classDeclaration.getStructure() });
62
+ ```
63
+
64
+ ### Traversing structures
65
+
66
+ #### `Structure` type guards
67
+
68
+ Similar to static methods found on `Node`, there is also a `Structure` export that you can use to check certain information about a structure.
69
+
70
+ For example:
71
+
72
+ ```ts setup: const structure: Structures;
73
+ import { Structure } from "ts-morph";
74
+
75
+ // ...etc...
76
+
77
+ if (Structure.isExportable(structure))
78
+ structure.isExported = false;
79
+ ```
80
+
81
+ #### `forEachStructureChild`
82
+
83
+ Similar to the compiler API's `forEachChild`, there is a `forEachStructureChild` method in ts-morph for navigating over a structure's children.
84
+
85
+ For example:
86
+
87
+ ```ts
88
+ import { forEachStructureChild, SourceFileStructure, Structure } from "ts-morph";
89
+
90
+ const structure: SourceFileStructure = {
91
+ kind: StructureKind.SourceFile,
92
+ statements: [{
93
+ kind: StructureKind.Function,
94
+ name: "myFunction",
95
+ parameters: [{ name: "myParam" }],
96
+ }],
97
+ };
98
+
99
+ forEachStructureChild(structure, child => {
100
+ if (Structure.hasName(child))
101
+ console.log(child.name);
102
+ });
103
+ ```
104
+
105
+ Outputs: `"myFunction"`
106
+
107
+ ##### Structures with no kind
108
+
109
+ Some structures have optional kinds. For example, in `parameters: [{ name: "myParam" }]` above, specifying `kind: StructureKind.Parameter` in the parameter would be unnecessarily repetitive. However, when using `forEachStructureChild`, you probably want to know the `kind` of the structure in order to do certain operations. For this reason, `forEachStructureChild` will automatically add the correct `kind` property to structures that don't have one.
110
+
111
+ ##### Finding a child structure
112
+
113
+ Note that unlike ts-morph's `forEachChild`, this function acts like the `forEachChild` in the compiler API and will return any truthy value returned in the second argument's function:
114
+
115
+ ```ts setup: const structure: SourceFileStructure;
116
+ const firstClassDecStructure = forEachStructureChild(structure, child => Structure.isClass(child) ? child : undefined);
117
+ ```