or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-usage.mdcodemods.mdconfiguration.mdindex.mdlanguage-server.mdprogrammatic-api.md

language-server.mddocs/

0

# Language Server

1

2

The Relay Compiler includes a full Language Server Protocol (LSP) implementation that provides IDE integration with real-time GraphQL validation, auto-completion, hover information, and go-to-definition functionality.

3

4

## Starting the Language Server

5

6

```bash

7

{ .api }

8

relay-compiler lsp [OPTIONS]

9

```

10

11

### Options

12

13

```bash

14

{ .api }

15

--config <PATH> # Config file path

16

--output <KIND> # Verbosity level (default: quiet-with-errors)

17

--locate-command <SCRIPT> # Script for GraphQL entity location lookup

18

```

19

20

### Output Levels

21

22

```typescript

23

{ .api }

24

type OutputKind = "debug" | "quiet" | "quiet-with-errors" | "verbose";

25

```

26

27

## Basic Usage

28

29

```bash

30

# Start with default configuration discovery

31

relay-compiler lsp

32

33

# Start with specific configuration

34

relay-compiler lsp --config ./relay.config.json

35

36

# Start with debug output for troubleshooting

37

relay-compiler lsp --output debug

38

39

# Start with custom entity location script

40

relay-compiler lsp --locate-command "./scripts/find-graphql-definition.sh"

41

```

42

43

## IDE Integration

44

45

### VS Code

46

47

The Relay LSP integrates with the official Relay extension for VS Code. The binary resolution logic is shared between the CLI and the extension.

48

49

**Installation:**

50

1. Install the Relay extension from the VS Code marketplace

51

2. Ensure `relay-compiler` is installed in your project

52

3. Configure your `relay.config.json`

53

4. The extension will automatically start the LSP

54

55

### Other IDEs

56

57

Any editor that supports LSP can integrate with the Relay language server:

58

59

- **Vim/Neovim**: Use LSP clients like `nvim-lspconfig` or `vim-lsp`

60

- **Emacs**: Use `lsp-mode` or `eglot`

61

- **Sublime Text**: Use `LSP` package

62

- **IntelliJ/WebStorm**: Built-in LSP support

63

64

## LSP Features

65

66

### Real-time Validation

67

68

The language server provides immediate feedback on GraphQL syntax and semantic errors:

69

70

```typescript

71

{ .api }

72

interface ValidationFeatures {

73

syntaxErrors: boolean; // GraphQL syntax validation

74

schemaValidation: boolean; // Schema conformance checking

75

relaySpecificRules: boolean; // Relay-specific validation rules

76

fragmentValidation: boolean; // Fragment usage validation

77

}

78

```

79

80

### Auto-completion

81

82

Context-aware completions for:

83

84

- Field names from GraphQL schema

85

- Fragment names

86

- Directive names and arguments

87

- Type names

88

- Enum values

89

90

### Hover Information

91

92

Rich hover tooltips showing:

93

94

- Field types and descriptions

95

- Argument types and documentation

96

- Fragment definitions

97

- Schema documentation

98

99

### Go-to-Definition

100

101

Navigate from usage to definition for:

102

103

- Fragment definitions

104

- Schema types and fields

105

- Custom scalar definitions

106

107

### Diagnostics

108

109

Real-time error and warning reporting:

110

111

```typescript

112

{ .api }

113

interface DiagnosticTypes {

114

errors: string[]; // Compilation errors

115

warnings: string[]; // Potential issues

116

deprecations: string[]; // Deprecated field usage

117

suggestions: string[]; // Code improvement suggestions

118

}

119

```

120

121

## Custom Entity Location

122

123

For implementation-first GraphQL schemas, you can provide a custom script to locate GraphQL entity definitions.

124

125

```bash

126

{ .api }

127

--locate-command <SCRIPT>

128

```

129

130

### Script Interface

131

132

The locate command script receives entity information and should return location details:

133

134

```bash

135

# Script input (stdin):

136

# JSON object with entity information

137

{

138

"type": "field" | "type" | "directive",

139

"name": "string",

140

"parent": "string",

141

"schema": "path/to/schema"

142

}

143

144

# Script output (stdout):

145

# JSON object with location information

146

{

147

"file": "path/to/file",

148

"line": 42,

149

"column": 15

150

}

151

```

152

153

### Example Locate Script

154

155

```bash

156

#!/bin/bash

157

# find-graphql-definition.sh

158

159

input=$(cat)

160

entity_type=$(echo "$input" | jq -r '.type')

161

entity_name=$(echo "$input" | jq -r '.name')

162

163

case "$entity_type" in

164

"field")

165

# Search for field definition in resolvers

166

location=$(grep -n "resolve.*$entity_name" src/resolvers/*.js | head -1)

167

;;

168

"type")

169

# Search for type definition

170

location=$(grep -n "type $entity_name" src/schema/*.js | head -1)

171

;;

172

esac

173

174

if [[ -n "$location" ]]; then

175

file=$(echo "$location" | cut -d':' -f1)

176

line=$(echo "$location" | cut -d':' -f2)

177

echo "{\"file\": \"$file\", \"line\": $line, \"column\": 1}"

178

fi

179

```

180

181

## LSP Configuration

182

183

The language server uses the same configuration as the CLI compiler. All configuration options apply to LSP functionality.

184

185

### Project-specific Settings

186

187

```json

188

{

189

"language": "typescript",

190

"src": "./src",

191

"schema": "./schema.graphql",

192

"schemaExtensions": ["./src/schema-extensions"],

193

"featureFlags": {

194

"enable_fragment_argument_transform": "enabled"

195

}

196

}

197

```

198

199

### Multi-project Support

200

201

The LSP automatically detects which project context applies based on the file being edited:

202

203

```json

204

{

205

"sources": {

206

"./apps/web/src": "web",

207

"./apps/mobile/src": "mobile"

208

},

209

"projects": {

210

"web": {

211

"language": "typescript",

212

"schema": "./apps/web/schema.graphql"

213

},

214

"mobile": {

215

"language": "typescript",

216

"schema": "./apps/mobile/schema.graphql"

217

}

218

}

219

}

220

```

221

222

## Schema Documentation Integration

223

224

The LSP can load and display schema documentation from various sources:

225

226

```typescript

227

{ .api }

228

interface SchemaDocumentationLoader {

229

loadFieldDocumentation(typeName: string, fieldName: string): Promise<string>;

230

loadTypeDocumentation(typeName: string): Promise<string>;

231

loadDirectiveDocumentation(directiveName: string): Promise<string>;

232

}

233

```

234

235

### Documentation Sources

236

237

- **SDL Comments**: Standard GraphQL SDL documentation comments

238

- **Custom Loaders**: External documentation systems

239

- **Markdown Files**: Documentation in markdown format

240

241

## Extra Data Provider

242

243

Extend LSP functionality with custom data providers:

244

245

```typescript

246

{ .api }

247

interface LSPExtraDataProvider {

248

getFieldDefinitionSourceInfo(

249

typeName: string,

250

fieldName: string

251

): Promise<FieldDefinitionSourceInfo>;

252

253

getFieldSchemaInfo(

254

typeName: string,

255

fieldName: string

256

): Promise<FieldSchemaInfo>;

257

}

258

259

interface FieldDefinitionSourceInfo {

260

filePath: string;

261

line: number;

262

column: number;

263

}

264

265

interface FieldSchemaInfo {

266

description?: string;

267

deprecationReason?: string;

268

defaultValue?: any;

269

}

270

```

271

272

### Custom Provider Example

273

274

```rust

275

use relay_lsp::{LSPExtraDataProvider, FieldDefinitionSourceInfo, FieldSchemaInfo};

276

277

pub struct CustomDataProvider {

278

schema_registry: SchemaRegistry,

279

}

280

281

impl LSPExtraDataProvider for CustomDataProvider {

282

async fn get_field_definition_source_info(

283

&self,

284

type_name: &str,

285

field_name: &str,

286

) -> Option<FieldDefinitionSourceInfo> {

287

// Custom logic to locate field definitions

288

self.schema_registry.find_field_source(type_name, field_name)

289

}

290

291

async fn get_field_schema_info(

292

&self,

293

type_name: &str,

294

field_name: &str,

295

) -> Option<FieldSchemaInfo> {

296

// Custom logic to provide field information

297

self.schema_registry.get_field_info(type_name, field_name)

298

}

299

}

300

```

301

302

## Error Handling

303

304

The LSP provides comprehensive error handling and reporting:

305

306

```typescript

307

{ .api }

308

interface LSPErrors {

309

ConfigurationError: string; // Invalid configuration

310

SchemaLoadError: string; // Schema loading failures

311

ValidationError: string; // GraphQL validation failures

312

FileSystemError: string; // File access issues

313

LocateCommandError: string; // Custom locate script failures

314

}

315

```

316

317

### Common Error Scenarios

318

319

- **Configuration not found**: LSP will show helpful configuration discovery information

320

- **Schema file missing**: Clear error with path resolution guidance

321

- **Invalid GraphQL syntax**: Real-time syntax error highlighting

322

- **Locate command failures**: Fallback to basic LSP functionality

323

324

## Performance Optimization

325

326

The LSP is optimized for large codebases:

327

328

### Incremental Updates

329

330

- Only reprocesses changed files

331

- Maintains in-memory schema cache

332

- Efficient fragment dependency tracking

333

334

### Memory Management

335

336

- Configurable cache limits

337

- Automatic cleanup of unused data

338

- Efficient string interning

339

340

### Watchman Integration

341

342

```bash

343

{ .api }

344

FORCE_NO_WATCHMAN=1 # Disable Watchman, use filesystem polling

345

```

346

347

When Watchman is available, the LSP uses it for efficient file watching. Otherwise, it falls back to filesystem polling.

348

349

## Troubleshooting

350

351

### Debug Mode

352

353

```bash

354

relay-compiler lsp --output debug

355

```

356

357

Debug mode provides detailed logging for:

358

- Configuration loading

359

- Schema parsing

360

- File watching events

361

- Validation cycles

362

- Custom locate command execution

363

364

### Log Output

365

366

The LSP writes logs to stderr, making it compatible with most LSP clients that capture and display server logs.

367

368

### Common Issues

369

370

1. **LSP not starting**: Check configuration file validity

371

2. **No completions**: Verify schema file accessibility

372

3. **Incorrect go-to-definition**: Configure locate command properly

373

4. **Performance issues**: Enable Watchman or reduce project size