or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-traversal.mdcode-analysis.mdcontrol-flow.mdindex.mdnode-typeguards.mdtext-processing.mdtype-guards.mdtype-utilities.mdvariable-usage.md

variable-usage.mddocs/

0

# Variable Usage Analysis

1

2

Specialized utilities for analyzing variable declarations, usage patterns, and scope analysis. These functions provide detailed information about variable domains, export status, usage locations, and declaration contexts within TypeScript source files.

3

4

## Capabilities

5

6

### Variable Usage Collection

7

8

Comprehensive analysis of variable usage throughout a source file.

9

10

```typescript { .api }

11

/**

12

* Collect complete variable usage information for a source file

13

* @param sourceFile - Source file to analyze

14

* @returns Map of identifiers to their usage information

15

*/

16

function collectVariableUsage(sourceFile: ts.SourceFile): Map<ts.Identifier, VariableInfo>;

17

18

/**

19

* Complete information about a variable's declaration and usage

20

*/

21

interface VariableInfo {

22

/** Declaration domain flags (namespace, type, value, import) */

23

domain: DeclarationDomain;

24

/** Whether variable is exported from module */

25

exported: boolean;

26

/** Array of all usage locations */

27

uses: VariableUse[];

28

/** Whether variable is declared in global scope */

29

inGlobalScope: boolean;

30

/** Array of all declaration identifiers */

31

declarations: ts.Identifier[];

32

}

33

34

/**

35

* Information about a specific variable usage

36

*/

37

interface VariableUse {

38

/** Usage domain flags (namespace, type, value, type query) */

39

domain: UsageDomain;

40

/** Identifier node representing the usage */

41

location: ts.Identifier;

42

}

43

```

44

45

### Declaration Domain Analysis

46

47

Utilities for determining what domains a variable declaration occupies.

48

49

```typescript { .api }

50

/**

51

* Get declaration domain for an identifier

52

* @param node - Identifier node to analyze

53

* @returns Declaration domain flags or undefined if not a declaration

54

*/

55

function getDeclarationDomain(node: ts.Identifier): DeclarationDomain | undefined;

56

57

/**

58

* Declaration domain enumeration

59

* Represents the semantic spaces a declaration can occupy

60

*/

61

enum DeclarationDomain {

62

/** Namespace declaration domain */

63

Namespace = 1,

64

/** Type declaration domain */

65

Type = 2,

66

/** Value declaration domain */

67

Value = 4,

68

/** Import declaration domain */

69

Import = 8,

70

/** Any declaration domain (namespace, type, or value) */

71

Any = Namespace | Type | Value

72

}

73

```

74

75

### Usage Domain Analysis

76

77

Utilities for determining how a variable is being used at specific locations.

78

79

```typescript { .api }

80

/**

81

* Get usage domain for an identifier

82

* @param node - Identifier node to analyze

83

* @returns Usage domain flags or undefined if not a usage

84

*/

85

function getUsageDomain(node: ts.Identifier): UsageDomain | undefined;

86

87

/**

88

* Usage domain enumeration

89

* Represents the semantic contexts in which a variable can be used

90

*/

91

enum UsageDomain {

92

/** Used as namespace (Module.member) */

93

Namespace = 1,

94

/** Used as type (: Type, <Type>) */

95

Type = 2,

96

/** Used as value (variable, function call) */

97

Value = 4,

98

/** Used as value or namespace */

99

ValueOrNamespace = Value | Namespace,

100

/** Used in any context */

101

Any = Namespace | Type | Value,

102

/** Used in typeof type query */

103

TypeQuery = 8

104

}

105

```

106

107

**Usage Examples:**

108

109

```typescript

110

import * as ts from "typescript";

111

import {

112

collectVariableUsage,

113

getDeclarationDomain,

114

getUsageDomain,

115

DeclarationDomain,

116

UsageDomain

117

} from "tsutils/util";

118

119

// Comprehensive variable analysis

120

function analyzeVariables(sourceFile: ts.SourceFile) {

121

const variableUsage = collectVariableUsage(sourceFile);

122

123

variableUsage.forEach((info, identifier) => {

124

console.log(`\nVariable: ${identifier.text}`);

125

console.log(` Exported: ${info.exported}`);

126

console.log(` Global scope: ${info.inGlobalScope}`);

127

console.log(` Declarations: ${info.declarations.length}`);

128

console.log(` Uses: ${info.uses.length}`);

129

130

// Analyze declaration domains

131

if (info.domain & DeclarationDomain.Namespace) {

132

console.log(" Declares namespace");

133

}

134

if (info.domain & DeclarationDomain.Type) {

135

console.log(" Declares type");

136

}

137

if (info.domain & DeclarationDomain.Value) {

138

console.log(" Declares value");

139

}

140

if (info.domain & DeclarationDomain.Import) {

141

console.log(" Import declaration");

142

}

143

144

// Analyze usage patterns

145

info.uses.forEach((use, index) => {

146

console.log(` Use ${index + 1}:`);

147

148

if (use.domain & UsageDomain.Namespace) {

149

console.log(" Used as namespace");

150

}

151

if (use.domain & UsageDomain.Type) {

152

console.log(" Used as type");

153

}

154

if (use.domain & UsageDomain.Value) {

155

console.log(" Used as value");

156

}

157

if (use.domain & UsageDomain.TypeQuery) {

158

console.log(" Used in typeof query");

159

}

160

161

console.log(` Location: line ${getLineNumber(sourceFile, use.location)}`);

162

});

163

});

164

}

165

166

// Declaration analysis

167

function analyzeDeclarations(sourceFile: ts.SourceFile) {

168

sourceFile.forEachChild(function visit(node) {

169

if (ts.isIdentifier(node)) {

170

const declarationDomain = getDeclarationDomain(node);

171

172

if (declarationDomain !== undefined) {

173

console.log(`Declaration "${node.text}"`);

174

175

if (declarationDomain & DeclarationDomain.Namespace) {

176

console.log(" Creates namespace");

177

}

178

if (declarationDomain & DeclarationDomain.Type) {

179

console.log(" Creates type");

180

}

181

if (declarationDomain & DeclarationDomain.Value) {

182

console.log(" Creates value");

183

}

184

}

185

}

186

187

node.forEachChild(visit);

188

});

189

}

190

191

// Usage pattern analysis

192

function analyzeUsagePatterns(sourceFile: ts.SourceFile) {

193

const typeUsages: ts.Identifier[] = [];

194

const valueUsages: ts.Identifier[] = [];

195

const namespaceUsages: ts.Identifier[] = [];

196

197

sourceFile.forEachChild(function visit(node) {

198

if (ts.isIdentifier(node)) {

199

const usageDomain = getUsageDomain(node);

200

201

if (usageDomain !== undefined) {

202

if (usageDomain & UsageDomain.Type) {

203

typeUsages.push(node);

204

}

205

if (usageDomain & UsageDomain.Value) {

206

valueUsages.push(node);

207

}

208

if (usageDomain & UsageDomain.Namespace) {

209

namespaceUsages.push(node);

210

}

211

}

212

}

213

214

node.forEachChild(visit);

215

});

216

217

console.log(`Type usages: ${typeUsages.length}`);

218

console.log(`Value usages: ${valueUsages.length}`);

219

console.log(`Namespace usages: ${namespaceUsages.length}`);

220

}

221

222

// Export analysis

223

function analyzeExports(sourceFile: ts.SourceFile) {

224

const variableUsage = collectVariableUsage(sourceFile);

225

const exportedVariables: string[] = [];

226

227

variableUsage.forEach((info, identifier) => {

228

if (info.exported) {

229

exportedVariables.push(identifier.text);

230

}

231

});

232

233

console.log("Exported variables:", exportedVariables);

234

}

235

236

// Scope analysis

237

function analyzeScopeLevel(sourceFile: ts.SourceFile) {

238

const variableUsage = collectVariableUsage(sourceFile);

239

const globalVariables: string[] = [];

240

const localVariables: string[] = [];

241

242

variableUsage.forEach((info, identifier) => {

243

if (info.inGlobalScope) {

244

globalVariables.push(identifier.text);

245

} else {

246

localVariables.push(identifier.text);

247

}

248

});

249

250

console.log(`Global variables: ${globalVariables.length}`);

251

console.log(`Local variables: ${localVariables.length}`);

252

}

253

254

// Cross-reference analysis

255

function analyzeCrossReferences(sourceFile: ts.SourceFile) {

256

const variableUsage = collectVariableUsage(sourceFile);

257

258

variableUsage.forEach((info, identifier) => {

259

if (info.uses.length === 0) {

260

console.log(`Unused variable: ${identifier.text}`);

261

} else if (info.declarations.length > 1) {

262

console.log(`Variable "${identifier.text}" has multiple declarations`);

263

}

264

265

// Check for mixed usage domains

266

const usageDomains = new Set(info.uses.map(use => use.domain));

267

if (usageDomains.size > 1) {

268

console.log(`Variable "${identifier.text}" used in multiple contexts`);

269

}

270

});

271

}

272

273

// Helper function for line number calculation

274

function getLineNumber(sourceFile: ts.SourceFile, node: ts.Node): number {

275

return sourceFile.getLineAndCharacterOfPosition(node.start).line + 1;

276

}

277

```

278

279

**Common Use Cases:**

280

281

1. **Unused Variable Detection**: Identify variables that are declared but never used

282

2. **Export Analysis**: Find all exported variables and their usage patterns

283

3. **Scope Analysis**: Determine variable scope levels and potential conflicts

284

4. **Cross-Reference Generation**: Build symbol tables and reference maps

285

5. **Refactoring Support**: Understand variable dependencies for safe refactoring

286

6. **Type vs Value Usage**: Distinguish between type-level and value-level usage of identifiers

287

7. **Import Analysis**: Track imported symbols and their usage throughout the file

288

8. **Declaration Merging**: Identify variables with multiple declarations (interfaces, namespaces)

289

290

The variable usage analysis utilities are particularly valuable for:

291

- Code analysis tools and linters

292

- Refactoring engines

293

- IDE features like "find all references"

294

- Dead code elimination

295

- Symbol navigation and intellisense

296

- Type checking and validation