0
# Language Module and Parsing
1
2
Core language registration and parsing infrastructure that integrates Scala with PMD's analysis framework. This module handles Scala version management, dialect configuration, and source code parsing using Scalameta.
3
4
## Capabilities
5
6
### Language Module Registration
7
8
Registers Scala language support with PMD framework and manages multiple Scala versions through dialect configuration.
9
10
```java { .api }
11
/**
12
* Language Module for Scala that registers with PMD's language system
13
*/
14
public class ScalaLanguageModule extends BaseLanguageModule {
15
/** The language name: "Scala" */
16
public static final String NAME = "Scala";
17
18
/** The terse name: "scala" */
19
public static final String TERSE_NAME = "scala";
20
21
/**
22
* Create a new instance of Scala Language Module.
23
* Automatically registers support for Scala versions 2.10, 2.11, 2.12, and 2.13
24
* with 2.13 as the default version.
25
*/
26
public ScalaLanguageModule();
27
}
28
```
29
30
**Usage Examples:**
31
32
```java
33
import net.sourceforge.pmd.lang.Language;
34
import net.sourceforge.pmd.lang.LanguageRegistry;
35
import net.sourceforge.pmd.lang.LanguageVersion;
36
import net.sourceforge.pmd.lang.scala.ScalaLanguageModule;
37
38
// Language module is automatically registered via SPI
39
// Located in META-INF/services/net.sourceforge.pmd.lang.Language
40
41
// Access registered language
42
Language scalaLang = LanguageRegistry.getLanguage(ScalaLanguageModule.NAME);
43
LanguageVersion defaultVersion = scalaLang.getDefaultVersion(); // Scala 2.13
44
LanguageVersion scala212 = scalaLang.getVersion("2.12");
45
```
46
47
### Language Version Handler
48
49
Manages Scala dialect-specific parsing and rule processing for different Scala versions.
50
51
```java { .api }
52
/**
53
* The Scala Language Handler implementation for version-specific operations
54
*/
55
public class ScalaLanguageHandler extends AbstractLanguageVersionHandler {
56
/**
57
* Create the Language Handler using the given Scala Dialect
58
* @param scalaDialect the language version to use while parsing
59
*/
60
public ScalaLanguageHandler(Dialect scalaDialect);
61
62
/**
63
* Get the Scala Dialect used in this language version choice
64
* @return the Scala Dialect for this handler
65
*/
66
public Dialect getDialect();
67
68
/**
69
* Get the rule violation factory for creating rule violations
70
* @return ScalaRuleViolationFactory instance
71
*/
72
@Override
73
public RuleViolationFactory getRuleViolationFactory();
74
75
/**
76
* Create a parser instance for the given options
77
* @param parserOptions parsing configuration options
78
* @return ScalaParser configured with this handler's dialect
79
*/
80
@Override
81
public ScalaParser getParser(ParserOptions parserOptions);
82
}
83
```
84
85
**Usage Examples:**
86
87
```java
88
import scala.meta.Dialect;
89
import scala.meta.dialects.package$;
90
91
// Create handler for specific Scala version
92
Dialect scala212 = package$.MODULE$.Scala212();
93
ScalaLanguageHandler handler = new ScalaLanguageHandler(scala212);
94
95
// Get parser for this version
96
ParserOptions options = new ParserOptions();
97
ScalaParser parser = handler.getParser(options);
98
99
// Access dialect information
100
Dialect currentDialect = handler.getDialect();
101
```
102
103
### Scala Source Parser
104
105
Parses Scala source code into PMD-compatible AST using Scalameta parsing technology.
106
107
```java { .api }
108
/**
109
* Scala's Parser implementation. Defers parsing to the scala compiler via
110
* Scalameta. This parser then wraps all of ScalaMeta's Nodes in Java versions
111
* for compatibility.
112
*/
113
public class ScalaParser extends AbstractParser {
114
/**
115
* Create a parser using the given Scala Dialect and set of parser options
116
* @param scalaDialect the Scala Dialect for this parser
117
* @param parserOptions any additional options for this parser
118
*/
119
public ScalaParser(Dialect scalaDialect, ParserOptions parserOptions);
120
121
/**
122
* Check if this parser can parse source code
123
* @return true, always returns true for Scala parser
124
*/
125
@Override
126
public boolean canParse();
127
128
/**
129
* Parse Scala source code into PMD AST
130
* @param fileName the name of the source file
131
* @param source reader providing the source code
132
* @return ASTSource representing the parsed Scala AST
133
* @throws ParseException if parsing fails
134
*/
135
@Override
136
public ASTSource parse(String fileName, Reader source) throws ParseException;
137
138
/**
139
* Get suppression map for ignoring warnings/errors
140
* @return empty map (not currently implemented)
141
*/
142
@Override
143
public Map<Integer, String> getSuppressMap();
144
145
/**
146
* Create token manager for source code
147
* @param source source code reader
148
* @return null (not used by Scala parser)
149
*/
150
@Override
151
protected TokenManager createTokenManager(Reader source);
152
}
153
```
154
155
**Usage Examples:**
156
157
```java
158
import net.sourceforge.pmd.lang.scala.ScalaParser;
159
import net.sourceforge.pmd.lang.scala.ast.ASTSource;
160
import java.io.StringReader;
161
162
// Create parser with Scala 2.12 dialect
163
Dialect scala212 = scala.meta.dialects.package$.MODULE$.Scala212();
164
ParserOptions options = new ParserOptions();
165
ScalaParser parser = new ScalaParser(scala212, options);
166
167
// Parse Scala source code
168
String scalaCode = """
169
object HelloWorld {
170
def main(args: Array[String]): Unit = {
171
println("Hello, World!")
172
}
173
}
174
""";
175
176
try (StringReader reader = new StringReader(scalaCode)) {
177
ASTSource ast = parser.parse("HelloWorld.scala", reader);
178
179
// AST is now ready for analysis
180
System.out.println("Parsed successfully: " + ast.getClass().getSimpleName());
181
} catch (ParseException e) {
182
System.err.println("Parse error: " + e.getMessage());
183
}
184
```
185
186
### AST Tree Builder
187
188
Converts Scalameta AST to PMD-compatible node hierarchy with proper parent-child relationships.
189
190
```java { .api }
191
/**
192
* Translates Scala's AST to a PMD-compatible AST
193
* @InternalApi - Not intended for direct use
194
*/
195
class ScalaTreeBuilder {
196
/**
197
* Construct a matching tree that implements the PMD Node interface
198
* @param <T> the scala node that extends the Tree trait
199
* @param astNode the Java node that extends the PMD Node interface
200
* @return a PMD compatible node representing the Scala AST node
201
*/
202
<T extends Tree> ScalaNode<T> build(T astNode);
203
}
204
```
205
206
## Error Handling
207
208
The parsing system handles errors through PMD's standard exception hierarchy:
209
210
```java { .api }
211
// Main parsing exception
212
public class ParseException extends Exception {
213
public ParseException(String message);
214
public ParseException(Throwable cause);
215
}
216
217
// Token manager errors from Scalameta
218
public class TokenMgrError extends Error {
219
public TokenMgrError(int line, int column, String filename, String message, Throwable cause);
220
}
221
```
222
223
**Common Error Scenarios:**
224
225
```java
226
try {
227
ASTSource ast = parser.parse("test.scala", sourceReader);
228
} catch (ParseException e) {
229
// Handle syntax errors, I/O errors, etc.
230
if (e.getCause() instanceof IOException) {
231
// I/O problem reading source
232
} else {
233
// Syntax error in Scala code
234
}
235
} catch (TokenMgrError e) {
236
// Low-level tokenization error from Scalameta
237
System.err.println("Tokenization failed at line " + e.getLine());
238
}
239
```
240
241
## Supported Scala Versions
242
243
The language module supports multiple Scala versions through Scalameta dialects:
244
245
- **Scala 2.10**: `scala.meta.dialects.package$.MODULE$.Scala210()`
246
- **Scala 2.11**: `scala.meta.dialects.package$.MODULE$.Scala211()`
247
- **Scala 2.12**: `scala.meta.dialects.package$.MODULE$.Scala212()` (default for this package)
248
- **Scala 2.13**: `scala.meta.dialects.package$.MODULE$.Scala213()` (default overall)
249
250
**Version Selection:**
251
252
```java
253
// Through language registry
254
LanguageVersion version = LanguageRegistry.getLanguage(ScalaLanguageModule.NAME)
255
.getVersion("2.12");
256
ScalaLanguageHandler handler = (ScalaLanguageHandler) version.getLanguageVersionHandler();
257
258
// Direct dialect creation
259
Dialect scala212 = scala.meta.dialects.package$.MODULE$.Scala212();
260
ScalaLanguageHandler directHandler = new ScalaLanguageHandler(scala212);
261
```