@tslite/services 0.0.0-stage → 1.12.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 (176) hide show
  1. package/LICENSE +55 -0
  2. package/NOTICE +13 -0
  3. package/dist/_namespaces/edit.d.ts +8 -0
  4. package/dist/_namespaces/edit.js +11 -0
  5. package/dist/_namespaces/ts.Completions.StringCompletions.d.ts +1 -0
  6. package/dist/_namespaces/ts.Completions.StringCompletions.js +2 -0
  7. package/dist/_namespaces/ts.Completions.d.ts +2 -0
  8. package/dist/_namespaces/ts.Completions.js +3 -0
  9. package/dist/_namespaces/ts.FindAllReferences.d.ts +2 -0
  10. package/dist/_namespaces/ts.FindAllReferences.js +3 -0
  11. package/dist/_namespaces/ts.GoToDefinition.d.ts +1 -0
  12. package/dist/_namespaces/ts.GoToDefinition.js +2 -0
  13. package/dist/_namespaces/ts.NavigationBar.d.ts +1 -0
  14. package/dist/_namespaces/ts.NavigationBar.js +2 -0
  15. package/dist/_namespaces/ts.OrganizeImports.d.ts +1 -0
  16. package/dist/_namespaces/ts.OrganizeImports.js +2 -0
  17. package/dist/_namespaces/ts.OutliningElementsCollector.d.ts +1 -0
  18. package/dist/_namespaces/ts.OutliningElementsCollector.js +2 -0
  19. package/dist/_namespaces/ts.Rename.d.ts +1 -0
  20. package/dist/_namespaces/ts.Rename.js +2 -0
  21. package/dist/_namespaces/ts.SignatureHelp.d.ts +1 -0
  22. package/dist/_namespaces/ts.SignatureHelp.js +2 -0
  23. package/dist/_namespaces/ts.SmartSelectionRange.d.ts +1 -0
  24. package/dist/_namespaces/ts.SmartSelectionRange.js +2 -0
  25. package/dist/_namespaces/ts.SymbolDisplay.d.ts +1 -0
  26. package/dist/_namespaces/ts.SymbolDisplay.js +2 -0
  27. package/dist/_namespaces/ts.codefix.d.ts +26 -0
  28. package/dist/_namespaces/ts.codefix.js +27 -0
  29. package/dist/_namespaces/ts.d.ts +17 -0
  30. package/dist/_namespaces/ts.formatting.d.ts +7 -0
  31. package/dist/_namespaces/ts.formatting.js +8 -0
  32. package/dist/_namespaces/ts.js +20 -0
  33. package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.d.ts +1 -0
  34. package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.js +2 -0
  35. package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.d.ts +1 -0
  36. package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.js +2 -0
  37. package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.d.ts +1 -0
  38. package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.js +2 -0
  39. package/dist/_namespaces/ts.refactor.d.ts +9 -0
  40. package/dist/_namespaces/ts.refactor.extractSymbol.d.ts +1 -0
  41. package/dist/_namespaces/ts.refactor.extractSymbol.js +2 -0
  42. package/dist/_namespaces/ts.refactor.js +10 -0
  43. package/dist/_namespaces/ts.textChanges.d.ts +1 -0
  44. package/dist/_namespaces/ts.textChanges.js +2 -0
  45. package/dist/classifier.d.ts +5 -0
  46. package/dist/classifier.js +439 -0
  47. package/dist/codeFixProvider.d.ts +13 -0
  48. package/dist/codeFixProvider.js +84 -0
  49. package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.d.ts +1 -0
  50. package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.js +21 -0
  51. package/dist/codefixes/addEmptyExportDeclaration.d.ts +1 -0
  52. package/dist/codefixes/addEmptyExportDeclaration.js +17 -0
  53. package/dist/codefixes/addMissingAsync.d.ts +1 -0
  54. package/dist/codefixes/addMissingAsync.js +75 -0
  55. package/dist/codefixes/addMissingAwait.d.ts +1 -0
  56. package/dist/codefixes/addMissingAwait.js +236 -0
  57. package/dist/codefixes/addMissingConst.d.ts +1 -0
  58. package/dist/codefixes/addMissingConst.js +91 -0
  59. package/dist/codefixes/addNameToNamelessParameter.d.ts +1 -0
  60. package/dist/codefixes/addNameToNamelessParameter.js +29 -0
  61. package/dist/codefixes/convertConstToLet.d.ts +1 -0
  62. package/dist/codefixes/convertConstToLet.js +30 -0
  63. package/dist/codefixes/convertToAsyncFunction.d.ts +1 -0
  64. package/dist/codefixes/convertToAsyncFunction.js +495 -0
  65. package/dist/codefixes/convertToMappedObjectType.d.ts +1 -0
  66. package/dist/codefixes/convertToMappedObjectType.js +48 -0
  67. package/dist/codefixes/correctQualifiedNameToIndexedAccessType.d.ts +1 -0
  68. package/dist/codefixes/correctQualifiedNameToIndexedAccessType.js +33 -0
  69. package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.d.ts +1 -0
  70. package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.js +27 -0
  71. package/dist/codefixes/fixAwaitInSyncFunction.d.ts +1 -0
  72. package/dist/codefixes/fixAwaitInSyncFunction.js +69 -0
  73. package/dist/codefixes/fixExpectedComma.d.ts +1 -0
  74. package/dist/codefixes/fixExpectedComma.js +35 -0
  75. package/dist/codefixes/fixInvalidJsxCharacters.d.ts +1 -0
  76. package/dist/codefixes/fixInvalidJsxCharacters.js +41 -0
  77. package/dist/codefixes/fixMissingCallParentheses.d.ts +1 -0
  78. package/dist/codefixes/fixMissingCallParentheses.js +42 -0
  79. package/dist/codefixes/fixSpelling.d.ts +1 -0
  80. package/dist/codefixes/fixSpelling.js +94 -0
  81. package/dist/codefixes/fixUnreachableCode.d.ts +1 -0
  82. package/dist/codefixes/fixUnreachableCode.js +65 -0
  83. package/dist/codefixes/fixUnusedIdentifier.d.ts +1 -0
  84. package/dist/codefixes/fixUnusedIdentifier.js +224 -0
  85. package/dist/codefixes/helpers.d.ts +8 -0
  86. package/dist/codefixes/helpers.js +53 -0
  87. package/dist/codefixes/importFixes.d.ts +14 -0
  88. package/dist/codefixes/importFixes.js +441 -0
  89. package/dist/codefixes/inferFromUsage.d.ts +1 -0
  90. package/dist/codefixes/inferFromUsage.js +742 -0
  91. package/dist/codefixes/removeUnnecessaryAwait.d.ts +1 -0
  92. package/dist/codefixes/removeUnnecessaryAwait.js +41 -0
  93. package/dist/codefixes/returnValueCorrect.d.ts +1 -0
  94. package/dist/codefixes/returnValueCorrect.js +132 -0
  95. package/dist/codefixes/splitTypeOnlyImport.d.ts +1 -0
  96. package/dist/codefixes/splitTypeOnlyImport.js +32 -0
  97. package/dist/codefixes/useBigintLiteral.d.ts +1 -0
  98. package/dist/codefixes/useBigintLiteral.js +29 -0
  99. package/dist/completions.d.ts +83 -0
  100. package/dist/completions.js +1720 -0
  101. package/dist/documentHighlights.d.ts +8 -0
  102. package/dist/documentHighlights.js +367 -0
  103. package/dist/documentRegistry.d.ts +36 -0
  104. package/dist/documentRegistry.js +63 -0
  105. package/dist/editingServices.d.ts +1 -0
  106. package/dist/editingServices.js +4 -0
  107. package/dist/findAllReferences.d.ts +113 -0
  108. package/dist/findAllReferences.js +1366 -0
  109. package/dist/formatting/formatting.d.ts +26 -0
  110. package/dist/formatting/formatting.js +1021 -0
  111. package/dist/formatting/formattingContext.d.ts +34 -0
  112. package/dist/formatting/formattingContext.js +78 -0
  113. package/dist/formatting/formattingScanner.d.ts +14 -0
  114. package/dist/formatting/formattingScanner.js +228 -0
  115. package/dist/formatting/rule.d.ts +31 -0
  116. package/dist/formatting/rule.js +22 -0
  117. package/dist/formatting/rules.d.ts +7 -0
  118. package/dist/formatting/rules.js +610 -0
  119. package/dist/formatting/rulesMap.d.ts +5 -0
  120. package/dist/formatting/rulesMap.js +127 -0
  121. package/dist/formatting/smartIndenter.d.ts +44 -0
  122. package/dist/formatting/smartIndenter.js +518 -0
  123. package/dist/getEditsForFileRename.d.ts +6 -0
  124. package/dist/getEditsForFileRename.js +86 -0
  125. package/dist/goToDefinition.d.ts +8 -0
  126. package/dist/goToDefinition.js +246 -0
  127. package/dist/importTracker.d.ts +50 -0
  128. package/dist/importTracker.js +422 -0
  129. package/dist/index.d.ts +1 -0
  130. package/dist/index.js +3 -0
  131. package/dist/navigationBar.d.ts +3 -0
  132. package/dist/navigationBar.js +549 -0
  133. package/dist/organizeImports.d.ts +18 -0
  134. package/dist/organizeImports.js +290 -0
  135. package/dist/outliningElementsCollector.d.ts +2 -0
  136. package/dist/outliningElementsCollector.js +261 -0
  137. package/dist/refactorProvider.d.ts +5 -0
  138. package/dist/refactorProvider.js +16 -0
  139. package/dist/refactors/addOrRemoveBracesToArrowFunction.d.ts +1 -0
  140. package/dist/refactors/addOrRemoveBracesToArrowFunction.js +86 -0
  141. package/dist/refactors/convertExport.d.ts +1 -0
  142. package/dist/refactors/convertExport.js +126 -0
  143. package/dist/refactors/convertImport.d.ts +1 -0
  144. package/dist/refactors/convertImport.js +116 -0
  145. package/dist/refactors/convertParamsToDestructuredObject.d.ts +1 -0
  146. package/dist/refactors/convertParamsToDestructuredObject.js +282 -0
  147. package/dist/refactors/convertStringOrTemplateLiteral.d.ts +1 -0
  148. package/dist/refactors/convertStringOrTemplateLiteral.js +148 -0
  149. package/dist/refactors/extractSymbol.d.ts +60 -0
  150. package/dist/refactors/extractSymbol.js +1281 -0
  151. package/dist/refactors/extractType.d.ts +1 -0
  152. package/dist/refactors/extractType.js +102 -0
  153. package/dist/refactors/moveToNewFile.d.ts +1 -0
  154. package/dist/refactors/moveToNewFile.js +477 -0
  155. package/dist/rename.d.ts +2 -0
  156. package/dist/rename.js +100 -0
  157. package/dist/services.d.ts +48 -0
  158. package/dist/services.js +1480 -0
  159. package/dist/signatureHelp.d.ts +8 -0
  160. package/dist/signatureHelp.js +414 -0
  161. package/dist/smartSelection.d.ts +2 -0
  162. package/dist/smartSelection.js +243 -0
  163. package/dist/stringCompletions.d.ts +4 -0
  164. package/dist/stringCompletions.js +220 -0
  165. package/dist/suggestionDiagnostics.d.ts +6 -0
  166. package/dist/suggestionDiagnostics.js +92 -0
  167. package/dist/symbolDisplay.d.ts +16 -0
  168. package/dist/symbolDisplay.js +400 -0
  169. package/dist/textChanges.d.ts +161 -0
  170. package/dist/textChanges.js +1163 -0
  171. package/dist/types.d.ts +908 -0
  172. package/dist/types.js +263 -0
  173. package/dist/utilities.d.ts +283 -0
  174. package/dist/utilities.js +1981 -0
  175. package/package.json +45 -3
  176. package/README.md +0 -3
@@ -0,0 +1,290 @@
1
+ // Modificado de microsoft/TypeScript v3.9.10, src/services/organizeImports.ts: o namespace virou módulo ES, com os imports explícitos.
2
+ // Saem o import da fábrica do JSX, que a tag tinha por usado sempre que o arquivo tem JSX (a fábrica é do emit, CK-19), e
3
+ // o import que um `declare module "x"` aumenta, que a tag mantinha mesmo sem uso (o módulo ambiente de nome em string,
4
+ // CK-02, princípio 4).
5
+ import { FindAllReferences, compareBooleans, compareStringsCaseInsensitive, createIdentifier, createImportSpecifier, createNamedImports, emptyArray, flatMap, getNewLineOrDefaultFromHost, group, isAmbientModule, isExportDeclaration, isExternalModuleNameRelative, isImportDeclaration, isNamedExports, isNamespaceImport, isStringLiteralLike, length, stableSort, suppressLeadingTrivia, textChanges, updateExportDeclaration, updateImportClause, updateImportDeclaration, updateNamedExports, updateNamedImports, updateNamespaceExport, } from "./_namespaces/edit.js";
6
+ /**
7
+ * Organize imports by:
8
+ * 1) Removing unused imports
9
+ * 2) Coalescing imports from the same module
10
+ * 3) Sorting imports
11
+ */
12
+ export function organizeImports(sourceFile, formatContext, host, program, preferences) {
13
+ const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext, preferences });
14
+ const coalesceAndOrganizeImports = (importGroup) => coalesceImports(removeUnusedImports(importGroup, sourceFile, program));
15
+ // All of the old ImportDeclarations in the file, in syntactic order.
16
+ const topLevelImportDecls = sourceFile.statements.filter(isImportDeclaration);
17
+ organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports);
18
+ // All of the old ExportDeclarations in the file, in syntactic order.
19
+ const topLevelExportDecls = sourceFile.statements.filter(isExportDeclaration);
20
+ organizeImportsWorker(topLevelExportDecls, coalesceExports);
21
+ for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) {
22
+ if (!ambientModule.body) {
23
+ continue;
24
+ }
25
+ const ambientModuleImportDecls = ambientModule.body.statements.filter(isImportDeclaration);
26
+ organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports);
27
+ const ambientModuleExportDecls = ambientModule.body.statements.filter(isExportDeclaration);
28
+ organizeImportsWorker(ambientModuleExportDecls, coalesceExports);
29
+ }
30
+ return changeTracker.getChanges();
31
+ function organizeImportsWorker(oldImportDecls, coalesce) {
32
+ if (length(oldImportDecls) === 0) {
33
+ return;
34
+ }
35
+ // Special case: normally, we'd expect leading and trailing trivia to follow each import
36
+ // around as it's sorted. However, we do not want this to happen for leading trivia
37
+ // on the first import because it is probably the header comment for the file.
38
+ // Consider: we could do a more careful check that this trivia is actually a header,
39
+ // but the consequences of being wrong are very minor.
40
+ suppressLeadingTrivia(oldImportDecls[0]);
41
+ const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier));
42
+ const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier));
43
+ const newImportDecls = flatMap(sortedImportGroups, importGroup => getExternalModuleName(importGroup[0].moduleSpecifier)
44
+ ? coalesce(importGroup)
45
+ : importGroup);
46
+ // Delete or replace the first import.
47
+ if (newImportDecls.length === 0) {
48
+ changeTracker.delete(sourceFile, oldImportDecls[0]);
49
+ }
50
+ else {
51
+ // Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
52
+ changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, {
53
+ leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, // Leave header comment in place
54
+ trailingTriviaOption: textChanges.TrailingTriviaOption.Include,
55
+ suffix: getNewLineOrDefaultFromHost(host, formatContext.options),
56
+ });
57
+ }
58
+ // Delete any subsequent imports.
59
+ for (let i = 1; i < oldImportDecls.length; i++) {
60
+ changeTracker.deleteNode(sourceFile, oldImportDecls[i]);
61
+ }
62
+ }
63
+ }
64
+ function removeUnusedImports(oldImports, sourceFile, program) {
65
+ const typeChecker = program.getTypeChecker();
66
+ const usedImports = [];
67
+ for (const importDecl of oldImports) {
68
+ const { importClause } = importDecl;
69
+ if (!importClause) {
70
+ // Imports without import clauses are assumed to be included for their side effects and are not removed.
71
+ usedImports.push(importDecl);
72
+ continue;
73
+ }
74
+ let { name, namedBindings } = importClause;
75
+ // Default import
76
+ if (name && !isDeclarationUsed(name)) {
77
+ name = undefined;
78
+ }
79
+ if (namedBindings) {
80
+ if (isNamespaceImport(namedBindings)) {
81
+ // Namespace import
82
+ if (!isDeclarationUsed(namedBindings.name)) {
83
+ namedBindings = undefined;
84
+ }
85
+ }
86
+ else {
87
+ // List of named imports
88
+ const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.name));
89
+ if (newElements.length < namedBindings.elements.length) {
90
+ namedBindings = newElements.length
91
+ ? updateNamedImports(namedBindings, newElements)
92
+ : undefined;
93
+ }
94
+ }
95
+ }
96
+ if (name || namedBindings) {
97
+ usedImports.push(updateImportDeclarationAndClause(importDecl, name, namedBindings));
98
+ }
99
+ // Na tag, o import que um `declare module "x"` do arquivo aumentava ficava, mesmo sem uso (CK-02, princípio 4).
100
+ }
101
+ return usedImports;
102
+ // Na tag, também o nome da fábrica do JSX, que contava como usado quando o arquivo tinha JSX (CK-19).
103
+ function isDeclarationUsed(identifier) {
104
+ return FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile);
105
+ }
106
+ }
107
+ function getExternalModuleName(specifier) {
108
+ return specifier !== undefined && isStringLiteralLike(specifier)
109
+ ? specifier.text
110
+ : undefined;
111
+ }
112
+ // Internal for testing
113
+ /**
114
+ * @param importGroup a list of ImportDeclarations, all with the same module name.
115
+ */
116
+ export function coalesceImports(importGroup) {
117
+ if (importGroup.length === 0) {
118
+ return importGroup;
119
+ }
120
+ const { importWithoutClause, typeOnlyImports, regularImports } = getCategorizedImports(importGroup);
121
+ const coalescedImports = [];
122
+ if (importWithoutClause) {
123
+ coalescedImports.push(importWithoutClause);
124
+ }
125
+ for (const group of [regularImports, typeOnlyImports]) {
126
+ const isTypeOnly = group === typeOnlyImports;
127
+ const { defaultImports, namespaceImports, namedImports } = group;
128
+ // Normally, we don't combine default and namespace imports, but it would be silly to
129
+ // produce two import declarations in this special case.
130
+ if (!isTypeOnly && defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) {
131
+ // Add the namespace import to the existing default ImportDeclaration.
132
+ const defaultImport = defaultImports[0];
133
+ coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); // TODO: GH#18217
134
+ continue;
135
+ }
136
+ const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) => compareIdentifiers(i1.importClause.namedBindings.name, i2.importClause.namedBindings.name)); // TODO: GH#18217
137
+ for (const namespaceImport of sortedNamespaceImports) {
138
+ // Drop the name, if any
139
+ coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings)); // TODO: GH#18217
140
+ }
141
+ if (defaultImports.length === 0 && namedImports.length === 0) {
142
+ continue;
143
+ }
144
+ let newDefaultImport;
145
+ const newImportSpecifiers = [];
146
+ if (defaultImports.length === 1) {
147
+ newDefaultImport = defaultImports[0].importClause.name;
148
+ }
149
+ else {
150
+ for (const defaultImport of defaultImports) {
151
+ newImportSpecifiers.push(createImportSpecifier(createIdentifier("default"), defaultImport.importClause.name)); // TODO: GH#18217
152
+ }
153
+ }
154
+ newImportSpecifiers.push(...flatMap(namedImports, i => i.importClause.namedBindings.elements)); // TODO: GH#18217
155
+ const sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers);
156
+ const importDecl = defaultImports.length > 0
157
+ ? defaultImports[0]
158
+ : namedImports[0];
159
+ const newNamedImports = sortedImportSpecifiers.length === 0
160
+ ? newDefaultImport
161
+ ? undefined
162
+ : createNamedImports(emptyArray)
163
+ : namedImports.length === 0
164
+ ? createNamedImports(sortedImportSpecifiers)
165
+ : updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); // TODO: GH#18217
166
+ // Type-only imports are not allowed to mix default, namespace, and named imports in any combination.
167
+ // We could rewrite a default import as a named import (`import { default as name }`), but we currently
168
+ // choose not to as a stylistic preference.
169
+ if (isTypeOnly && newDefaultImport && newNamedImports) {
170
+ coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, /*namedBindings*/ undefined));
171
+ coalescedImports.push(updateImportDeclarationAndClause(namedImports[0] ?? importDecl, /*name*/ undefined, newNamedImports));
172
+ }
173
+ else {
174
+ coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports));
175
+ }
176
+ }
177
+ return coalescedImports;
178
+ }
179
+ /*
180
+ * Returns entire import declarations because they may already have been rewritten and
181
+ * may lack parent pointers. The desired parts can easily be recovered based on the
182
+ * categorization.
183
+ *
184
+ * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`.
185
+ */
186
+ function getCategorizedImports(importGroup) {
187
+ let importWithoutClause;
188
+ const typeOnlyImports = { defaultImports: [], namespaceImports: [], namedImports: [] };
189
+ const regularImports = { defaultImports: [], namespaceImports: [], namedImports: [] };
190
+ for (const importDeclaration of importGroup) {
191
+ if (importDeclaration.importClause === undefined) {
192
+ // Only the first such import is interesting - the others are redundant.
193
+ // Note: Unfortunately, we will lose trivia that was on this node.
194
+ importWithoutClause = importWithoutClause || importDeclaration;
195
+ continue;
196
+ }
197
+ const group = importDeclaration.importClause.isTypeOnly ? typeOnlyImports : regularImports;
198
+ const { name, namedBindings } = importDeclaration.importClause;
199
+ if (name) {
200
+ group.defaultImports.push(importDeclaration);
201
+ }
202
+ if (namedBindings) {
203
+ if (isNamespaceImport(namedBindings)) {
204
+ group.namespaceImports.push(importDeclaration);
205
+ }
206
+ else {
207
+ group.namedImports.push(importDeclaration);
208
+ }
209
+ }
210
+ }
211
+ return {
212
+ importWithoutClause,
213
+ typeOnlyImports,
214
+ regularImports,
215
+ };
216
+ }
217
+ // Internal for testing
218
+ /**
219
+ * @param exportGroup a list of ExportDeclarations, all with the same module name.
220
+ */
221
+ export function coalesceExports(exportGroup) {
222
+ if (exportGroup.length === 0) {
223
+ return exportGroup;
224
+ }
225
+ const { exportWithoutClause, namedExports, typeOnlyExports } = getCategorizedExports(exportGroup);
226
+ const coalescedExports = [];
227
+ if (exportWithoutClause) {
228
+ coalescedExports.push(exportWithoutClause);
229
+ }
230
+ for (const exportGroup of [namedExports, typeOnlyExports]) {
231
+ if (exportGroup.length === 0) {
232
+ continue;
233
+ }
234
+ const newExportSpecifiers = [];
235
+ newExportSpecifiers.push(...flatMap(exportGroup, i => i.exportClause && isNamedExports(i.exportClause) ? i.exportClause.elements : emptyArray));
236
+ const sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers);
237
+ const exportDecl = exportGroup[0];
238
+ coalescedExports.push(updateExportDeclaration(exportDecl, exportDecl.modifiers, exportDecl.exportClause && (isNamedExports(exportDecl.exportClause) ?
239
+ updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) :
240
+ updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name)), exportDecl.moduleSpecifier, exportDecl.isTypeOnly));
241
+ }
242
+ return coalescedExports;
243
+ /*
244
+ * Returns entire export declarations because they may already have been rewritten and
245
+ * may lack parent pointers. The desired parts can easily be recovered based on the
246
+ * categorization.
247
+ */
248
+ function getCategorizedExports(exportGroup) {
249
+ let exportWithoutClause;
250
+ const namedExports = [];
251
+ const typeOnlyExports = [];
252
+ for (const exportDeclaration of exportGroup) {
253
+ if (exportDeclaration.exportClause === undefined) {
254
+ // Only the first such export is interesting - the others are redundant.
255
+ // Note: Unfortunately, we will lose trivia that was on this node.
256
+ exportWithoutClause = exportWithoutClause || exportDeclaration;
257
+ }
258
+ else if (exportDeclaration.isTypeOnly) {
259
+ typeOnlyExports.push(exportDeclaration);
260
+ }
261
+ else {
262
+ namedExports.push(exportDeclaration);
263
+ }
264
+ }
265
+ return {
266
+ exportWithoutClause,
267
+ namedExports,
268
+ typeOnlyExports,
269
+ };
270
+ }
271
+ }
272
+ function updateImportDeclarationAndClause(importDeclaration, name, namedBindings) {
273
+ return updateImportDeclaration(importDeclaration, importDeclaration.modifiers, updateImportClause(importDeclaration.importClause, name, namedBindings, importDeclaration.importClause.isTypeOnly), // TODO: GH#18217
274
+ importDeclaration.moduleSpecifier);
275
+ }
276
+ function sortSpecifiers(specifiers) {
277
+ return stableSort(specifiers, (s1, s2) => compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) ||
278
+ compareIdentifiers(s1.name, s2.name));
279
+ }
280
+ /* internal */ // Exported for testing
281
+ export function compareModuleSpecifiers(m1, m2) {
282
+ const name1 = getExternalModuleName(m1);
283
+ const name2 = getExternalModuleName(m2);
284
+ return compareBooleans(name1 === undefined, name2 === undefined) ||
285
+ compareBooleans(isExternalModuleNameRelative(name1), isExternalModuleNameRelative(name2)) ||
286
+ compareStringsCaseInsensitive(name1, name2);
287
+ }
288
+ function compareIdentifiers(s1, s2) {
289
+ return compareStringsCaseInsensitive(s1.text, s2.text);
290
+ }
@@ -0,0 +1,2 @@
1
+ import type { CancellationToken, OutliningSpan, SourceFile } from "./_namespaces/ts.js";
2
+ export declare function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[];
@@ -0,0 +1,261 @@
1
+ // Modificado de microsoft/TypeScript v3.9.10, src/services/outliningElementsCollector.ts: o namespace virou módulo ES, com os imports explícitos.
2
+ import { Debug, SyntaxKind, createTextSpanFromBounds, createTextSpanFromNode, createTextSpanFromRange, findAncestor, findChildOfKind, getLeadingCommentRangesOfNode, getSingleInitializerOfVariableStatementOrPropertyDeclaration, isAnyImportSyntax, isArrayLiteralExpression, isArrowFunction, isCallExpression, isDeclaration, isFunctionLike, isIfStatement, isInComment, isNodeArrayMultiLine, isVariableStatement, } from "./_namespaces/ts.js";
3
+ export function collectElements(sourceFile, cancellationToken) {
4
+ const res = [];
5
+ addNodeOutliningSpans(sourceFile, cancellationToken, res);
6
+ addRegionOutliningSpans(sourceFile, res);
7
+ return res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start);
8
+ }
9
+ function addNodeOutliningSpans(sourceFile, cancellationToken, out) {
10
+ let depthRemaining = 40;
11
+ let current = 0;
12
+ // Includes the EOF Token so that comments which aren't attached to statements are included
13
+ const statements = [...sourceFile.statements, sourceFile.endOfFileToken];
14
+ const n = statements.length;
15
+ while (current < n) {
16
+ while (current < n && !isAnyImportSyntax(statements[current])) {
17
+ visitNonImportNode(statements[current]);
18
+ current++;
19
+ }
20
+ if (current === n)
21
+ break;
22
+ const firstImport = current;
23
+ while (current < n && isAnyImportSyntax(statements[current])) {
24
+ addOutliningForLeadingCommentsForNode(statements[current], sourceFile, cancellationToken, out);
25
+ current++;
26
+ }
27
+ const lastImport = current - 1;
28
+ if (lastImport !== firstImport) {
29
+ out.push(createOutliningSpanFromBounds(findChildOfKind(statements[firstImport], SyntaxKind.ImportKeyword, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports" /* OutliningSpanKind.Imports */));
30
+ }
31
+ }
32
+ function visitNonImportNode(n) {
33
+ if (depthRemaining === 0)
34
+ return;
35
+ cancellationToken.throwIfCancellationRequested();
36
+ if (isDeclaration(n) || n.kind === SyntaxKind.EndOfFileToken) {
37
+ addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out);
38
+ }
39
+ if (isFunctionExpressionAssignedToVariable(n)) {
40
+ addOutliningForLeadingCommentsForNode(n.parent.parent.parent, sourceFile, cancellationToken, out);
41
+ }
42
+ const span = getOutliningSpanForNode(n, sourceFile);
43
+ if (span)
44
+ out.push(span);
45
+ depthRemaining--;
46
+ if (isCallExpression(n)) {
47
+ depthRemaining++;
48
+ visitNonImportNode(n.expression);
49
+ depthRemaining--;
50
+ n.arguments.forEach(visitNonImportNode);
51
+ n.typeArguments?.forEach(visitNonImportNode);
52
+ }
53
+ else if (isIfStatement(n) && n.elseStatement && isIfStatement(n.elseStatement)) {
54
+ // Consider an 'else if' to be on the same depth as the 'if'.
55
+ visitNonImportNode(n.expression);
56
+ visitNonImportNode(n.thenStatement);
57
+ depthRemaining++;
58
+ visitNonImportNode(n.elseStatement);
59
+ depthRemaining--;
60
+ }
61
+ else {
62
+ n.forEachChild(visitNonImportNode);
63
+ }
64
+ depthRemaining++;
65
+ }
66
+ /** A arrow atribuída a uma variável. Na tag, também a function expression (CK-02). */
67
+ function isFunctionExpressionAssignedToVariable(n) {
68
+ if (!isArrowFunction(n)) {
69
+ return false;
70
+ }
71
+ const ancestor = findAncestor(n, isVariableStatement);
72
+ return !!ancestor && getSingleInitializerOfVariableStatementOrPropertyDeclaration(ancestor) === n;
73
+ }
74
+ }
75
+ function addRegionOutliningSpans(sourceFile, out) {
76
+ const regions = [];
77
+ const lineStarts = sourceFile.getLineStarts();
78
+ for (const currentLineStart of lineStarts) {
79
+ const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart);
80
+ const lineText = sourceFile.text.substring(currentLineStart, lineEnd);
81
+ const result = isRegionDelimiter(lineText);
82
+ if (!result || isInComment(sourceFile, currentLineStart)) {
83
+ continue;
84
+ }
85
+ if (!result[1]) {
86
+ const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd);
87
+ regions.push(createOutliningSpan(span, "region" /* OutliningSpanKind.Region */, span, /*autoCollapse*/ false, result[2] || "#region"));
88
+ }
89
+ else {
90
+ const region = regions.pop();
91
+ if (region) {
92
+ region.textSpan.length = lineEnd - region.textSpan.start;
93
+ region.hintSpan.length = lineEnd - region.textSpan.start;
94
+ out.push(region);
95
+ }
96
+ }
97
+ }
98
+ }
99
+ const regionDelimiterRegExp = /^\s*\/\/\s*#(end)?region(?:\s+(.*))?(?:\r)?$/;
100
+ function isRegionDelimiter(lineText) {
101
+ return regionDelimiterRegExp.exec(lineText);
102
+ }
103
+ function addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out) {
104
+ const comments = getLeadingCommentRangesOfNode(n, sourceFile);
105
+ if (!comments)
106
+ return;
107
+ let firstSingleLineCommentStart = -1;
108
+ let lastSingleLineCommentEnd = -1;
109
+ let singleLineCommentCount = 0;
110
+ const sourceText = sourceFile.getFullText();
111
+ for (const { kind, pos, end } of comments) {
112
+ cancellationToken.throwIfCancellationRequested();
113
+ switch (kind) {
114
+ case SyntaxKind.SingleLineCommentTrivia:
115
+ // never fold region delimiters into single-line comment regions
116
+ const commentText = sourceText.slice(pos, end);
117
+ if (isRegionDelimiter(commentText)) {
118
+ combineAndAddMultipleSingleLineComments();
119
+ singleLineCommentCount = 0;
120
+ break;
121
+ }
122
+ // For single line comments, combine consecutive ones (2 or more) into
123
+ // a single span from the start of the first till the end of the last
124
+ if (singleLineCommentCount === 0) {
125
+ firstSingleLineCommentStart = pos;
126
+ }
127
+ lastSingleLineCommentEnd = end;
128
+ singleLineCommentCount++;
129
+ break;
130
+ case SyntaxKind.MultiLineCommentTrivia:
131
+ combineAndAddMultipleSingleLineComments();
132
+ out.push(createOutliningSpanFromBounds(pos, end, "comment" /* OutliningSpanKind.Comment */));
133
+ singleLineCommentCount = 0;
134
+ break;
135
+ default:
136
+ Debug.assertNever(kind);
137
+ }
138
+ }
139
+ combineAndAddMultipleSingleLineComments();
140
+ function combineAndAddMultipleSingleLineComments() {
141
+ // Only outline spans of two or more consecutive single line comments
142
+ if (singleLineCommentCount > 1) {
143
+ out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment" /* OutliningSpanKind.Comment */));
144
+ }
145
+ }
146
+ }
147
+ function createOutliningSpanFromBounds(pos, end, kind) {
148
+ return createOutliningSpan(createTextSpanFromBounds(pos, end), kind);
149
+ }
150
+ function getOutliningSpanForNode(n, sourceFile) {
151
+ switch (n.kind) {
152
+ case SyntaxKind.Block:
153
+ if (isFunctionLike(n.parent)) {
154
+ return functionSpan(n.parent, n, sourceFile);
155
+ }
156
+ // Check if the block is standalone, or 'attached' to some parent statement.
157
+ // If the latter, we want to collapse the block, but consider its hint span
158
+ // to be the entire span of the parent.
159
+ switch (n.parent.kind) {
160
+ case SyntaxKind.DoStatement:
161
+ case SyntaxKind.ForInStatement:
162
+ case SyntaxKind.ForOfStatement:
163
+ case SyntaxKind.ForStatement:
164
+ case SyntaxKind.IfStatement:
165
+ case SyntaxKind.WhileStatement:
166
+ // Na tag, também o `with` (CK-02).
167
+ case SyntaxKind.CatchClause:
168
+ return spanForNode(n.parent);
169
+ case SyntaxKind.TryStatement:
170
+ // Could be the try-block, or the finally-block.
171
+ const tryStatement = n.parent;
172
+ if (tryStatement.tryBlock === n) {
173
+ return spanForNode(n.parent);
174
+ }
175
+ else if (tryStatement.finallyBlock === n) {
176
+ const node = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
177
+ if (node)
178
+ return spanForNode(node);
179
+ }
180
+ // falls through
181
+ default:
182
+ // Block was a standalone block. In this case we want to only collapse
183
+ // the span of the block, independent of any parent span.
184
+ return createOutliningSpan(createTextSpanFromNode(n, sourceFile), "code" /* OutliningSpanKind.Code */);
185
+ }
186
+ case SyntaxKind.ModuleBlock:
187
+ return spanForNode(n.parent);
188
+ // Na tag, também a classe, a class expression, a interface e o enum (CK-02).
189
+ case SyntaxKind.CaseBlock:
190
+ case SyntaxKind.TypeLiteral:
191
+ return spanForNode(n);
192
+ case SyntaxKind.CaseClause:
193
+ case SyntaxKind.DefaultClause:
194
+ return spanForNodeArray(n.statements);
195
+ case SyntaxKind.ObjectLiteralExpression:
196
+ return spanForObjectOrArrayLiteral(n);
197
+ case SyntaxKind.ArrayLiteralExpression:
198
+ return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken);
199
+ case SyntaxKind.JsxElement:
200
+ return spanForJSXElement(n);
201
+ case SyntaxKind.JsxFragment:
202
+ return spanForJSXFragment(n);
203
+ case SyntaxKind.JsxSelfClosingElement:
204
+ case SyntaxKind.JsxOpeningElement:
205
+ return spanForJSXAttributes(n.attributes);
206
+ case SyntaxKind.TemplateExpression:
207
+ case SyntaxKind.NoSubstitutionTemplateLiteral:
208
+ return spanForTemplateLiteral(n);
209
+ }
210
+ function spanForJSXElement(node) {
211
+ const textSpan = createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd());
212
+ const tagName = node.openingElement.tagName.getText(sourceFile);
213
+ const bannerText = "<" + tagName + ">...</" + tagName + ">";
214
+ return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.Code */, textSpan, /*autoCollapse*/ false, bannerText);
215
+ }
216
+ function spanForJSXFragment(node) {
217
+ const textSpan = createTextSpanFromBounds(node.openingFragment.getStart(sourceFile), node.closingFragment.getEnd());
218
+ const bannerText = "<>...</>";
219
+ return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.Code */, textSpan, /*autoCollapse*/ false, bannerText);
220
+ }
221
+ function spanForJSXAttributes(node) {
222
+ if (node.properties.length === 0) {
223
+ return undefined;
224
+ }
225
+ return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* OutliningSpanKind.Code */);
226
+ }
227
+ function spanForTemplateLiteral(node) {
228
+ if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.text.length === 0) {
229
+ return undefined;
230
+ }
231
+ return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* OutliningSpanKind.Code */);
232
+ }
233
+ function spanForObjectOrArrayLiteral(node, open = SyntaxKind.OpenBraceToken) {
234
+ // If the block has no leading keywords and is inside an array literal or call expression,
235
+ // we only want to collapse the span of the block.
236
+ // Otherwise, the collapsed section will include the end of the previous line.
237
+ return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open);
238
+ }
239
+ function spanForNode(hintSpanNode, autoCollapse = false, useFullStart = true, open = SyntaxKind.OpenBraceToken, close = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken) {
240
+ const openToken = findChildOfKind(n, open, sourceFile);
241
+ const closeToken = findChildOfKind(n, close, sourceFile);
242
+ return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart);
243
+ }
244
+ function spanForNodeArray(nodeArray) {
245
+ return nodeArray.length ? createOutliningSpan(createTextSpanFromRange(nodeArray), "code" /* OutliningSpanKind.Code */) : undefined;
246
+ }
247
+ }
248
+ function functionSpan(node, body, sourceFile) {
249
+ const openToken = isNodeArrayMultiLine(node.parameters, sourceFile)
250
+ ? findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile)
251
+ : findChildOfKind(body, SyntaxKind.OpenBraceToken, sourceFile);
252
+ const closeToken = findChildOfKind(body, SyntaxKind.CloseBraceToken, sourceFile);
253
+ return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== SyntaxKind.ArrowFunction);
254
+ }
255
+ function spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse = false, useFullStart = true) {
256
+ const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd());
257
+ return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.Code */, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse);
258
+ }
259
+ function createOutliningSpan(textSpan, kind, hintSpan = textSpan, autoCollapse = false, bannerText = "...") {
260
+ return { textSpan, kind, hintSpan, bannerText, autoCollapse };
261
+ }
@@ -0,0 +1,5 @@
1
+ import type { ApplicableRefactorInfo, Refactor, RefactorContext, RefactorEditInfo } from "./_namespaces/edit.js";
2
+ /** @param name An unique code associated with each refactor. Does not have to be human-readable. */
3
+ export declare function registerRefactor(name: string, refactor: Refactor): void;
4
+ export declare function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[];
5
+ export declare function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string): RefactorEditInfo | undefined;
@@ -0,0 +1,16 @@
1
+ // Modificado de microsoft/TypeScript v3.9.10, src/services/refactorProvider.ts: o namespace virou módulo ES, com os imports explícitos.
2
+ import { arrayFrom, createMap, flatMapIterator, } from "./_namespaces/edit.js";
3
+ // A map with the refactor code as key, the refactor itself as value
4
+ // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want
5
+ const refactors = createMap();
6
+ /** @param name An unique code associated with each refactor. Does not have to be human-readable. */
7
+ export function registerRefactor(name, refactor) {
8
+ refactors.set(name, refactor);
9
+ }
10
+ export function getApplicableRefactors(context) {
11
+ return arrayFrom(flatMapIterator(refactors.values(), refactor => context.cancellationToken && context.cancellationToken.isCancellationRequested() ? undefined : refactor.getAvailableActions(context)));
12
+ }
13
+ export function getEditsForRefactor(context, refactorName, actionName) {
14
+ const refactor = refactors.get(refactorName);
15
+ return refactor && refactor.getEditsForAction(context, actionName);
16
+ }
@@ -0,0 +1,86 @@
1
+ // Modificado de microsoft/TypeScript v3.9.10, src/services/refactors/addOrRemoveBracesToArrowFunction.ts: o namespace virou módulo ES, com os imports explícitos.
2
+ import { Debug, Diagnostics, SyntaxKind, copyLeadingComments, copyTrailingAsLeadingComments, copyTrailingComments, createBlock, createIdentifier, createParen, createReturn, emptyArray, first, getContainingFunction, getTokenAtPosition, isArrowFunction, isExpression, isReturnStatement, needsParentheses, rangeContainsRange, suppressLeadingAndTrailingTrivia, textChanges, } from "../_namespaces/edit.js";
3
+ import { registerRefactor, } from "../_namespaces/ts.refactor.js";
4
+ const refactorName = "Add or remove braces in an arrow function";
5
+ const refactorDescription = Diagnostics.Add_or_remove_braces_in_an_arrow_function.message;
6
+ const addBracesActionName = "Add braces to arrow function";
7
+ const removeBracesActionName = "Remove braces from arrow function";
8
+ const addBracesActionDescription = Diagnostics.Add_braces_to_arrow_function.message;
9
+ const removeBracesActionDescription = Diagnostics.Remove_braces_from_arrow_function.message;
10
+ registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
11
+ function getAvailableActions(context) {
12
+ const { file, startPosition } = context;
13
+ const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
14
+ if (!info)
15
+ return emptyArray;
16
+ return [{
17
+ name: refactorName,
18
+ description: refactorDescription,
19
+ actions: [
20
+ info.addBraces ?
21
+ {
22
+ name: addBracesActionName,
23
+ description: addBracesActionDescription
24
+ } : {
25
+ name: removeBracesActionName,
26
+ description: removeBracesActionDescription
27
+ }
28
+ ]
29
+ }];
30
+ }
31
+ function getEditsForAction(context, actionName) {
32
+ const { file, startPosition } = context;
33
+ const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
34
+ if (!info)
35
+ return undefined;
36
+ const { expression, returnStatement, func } = info;
37
+ let body;
38
+ if (actionName === addBracesActionName) {
39
+ const returnStatement = createReturn(expression);
40
+ body = createBlock([returnStatement], /* multiLine */ true);
41
+ suppressLeadingAndTrailingTrivia(body);
42
+ copyLeadingComments(expression, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true);
43
+ }
44
+ else if (actionName === removeBracesActionName && returnStatement) {
45
+ // O corpo `{ return; }` vira o `undefined`, e não o `void 0` da tag: o operador `void` saiu da Linguagem
46
+ // (CK-63, CK-69).
47
+ const actualExpression = expression || createIdentifier("undefined");
48
+ body = needsParentheses(actualExpression) ? createParen(actualExpression) : actualExpression;
49
+ suppressLeadingAndTrailingTrivia(body);
50
+ copyTrailingAsLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
51
+ copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
52
+ copyTrailingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
53
+ }
54
+ else {
55
+ Debug.fail("invalid action");
56
+ }
57
+ const edits = textChanges.ChangeTracker.with(context, t => {
58
+ t.replaceNode(file, func.body, body);
59
+ });
60
+ return { renameFilename: undefined, renameLocation: undefined, edits };
61
+ }
62
+ function getConvertibleArrowFunctionAtPosition(file, startPosition) {
63
+ const node = getTokenAtPosition(file, startPosition);
64
+ const func = getContainingFunction(node);
65
+ if (!func || !isArrowFunction(func) || (!rangeContainsRange(func, node) || rangeContainsRange(func.body, node)))
66
+ return undefined;
67
+ if (isExpression(func.body)) {
68
+ return {
69
+ func,
70
+ addBraces: true,
71
+ expression: func.body
72
+ };
73
+ }
74
+ else if (func.body.statements.length === 1) {
75
+ const firstStatement = first(func.body.statements);
76
+ if (isReturnStatement(firstStatement)) {
77
+ return {
78
+ func,
79
+ addBraces: false,
80
+ expression: firstStatement.expression,
81
+ returnStatement: firstStatement
82
+ };
83
+ }
84
+ }
85
+ return undefined;
86
+ }