|
5 | 5 | import static io.protostuff.compiler.parser.ProtoLexer.NL; |
6 | 6 | import static io.protostuff.compiler.parser.ProtoLexer.STRING_VALUE; |
7 | 7 | import static io.protostuff.compiler.parser.ProtoLexer.WS; |
| 8 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_customFieldReference; |
| 9 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_enumBlock; |
| 10 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_enumField; |
| 11 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_enumName; |
| 12 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_extendBlock; |
| 13 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_extendBlockEntry; |
| 14 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_extensions; |
| 15 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_field; |
| 16 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_fieldModifier; |
| 17 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_fieldName; |
| 18 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_fieldRerefence; |
| 19 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_fileReference; |
| 20 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_groupBlock; |
| 21 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_ident; |
| 22 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_importStatement; |
| 23 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_map; |
| 24 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_mapKey; |
| 25 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_messageBlock; |
| 26 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_messageName; |
| 27 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_oneof; |
| 28 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_oneofName; |
| 29 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_option; |
| 30 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_optionEntry; |
| 31 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_optionValue; |
| 32 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_packageStatement; |
| 33 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_proto; |
| 34 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_range; |
| 35 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_reservedFieldNames; |
| 36 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_reservedFieldRanges; |
| 37 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_rpcMethod; |
| 38 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_rpcName; |
| 39 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_rpcType; |
| 40 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_serviceBlock; |
| 41 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_serviceName; |
| 42 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_standardFieldRerefence; |
| 43 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_syntaxStatement; |
| 44 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_tag; |
| 45 | +import static io.protostuff.compiler.parser.ProtoParser.RULE_typeReference; |
| 46 | +import static io.protostuff.compiler.parser.ProtoParser.ruleNames; |
8 | 47 |
|
9 | 48 | import com.intellij.lang.ASTNode; |
10 | 49 | import com.intellij.lang.ParserDefinition; |
11 | 50 | import com.intellij.lang.PsiParser; |
12 | 51 | import com.intellij.lexer.Lexer; |
| 52 | +import com.intellij.openapi.diagnostic.Logger; |
13 | 53 | import com.intellij.openapi.project.Project; |
14 | 54 | import com.intellij.psi.FileViewProvider; |
15 | 55 | import com.intellij.psi.PsiFile; |
|
27 | 67 | import io.protostuff.jetbrains.plugin.psi.FieldNode; |
28 | 68 | import io.protostuff.jetbrains.plugin.psi.FieldReferenceNode; |
29 | 69 | import io.protostuff.jetbrains.plugin.psi.FileReferenceNode; |
| 70 | +import io.protostuff.jetbrains.plugin.psi.GenericNameNode; |
30 | 71 | import io.protostuff.jetbrains.plugin.psi.GroupNode; |
31 | 72 | import io.protostuff.jetbrains.plugin.psi.ImportNode; |
32 | 73 | import io.protostuff.jetbrains.plugin.psi.MapKeyNode; |
33 | 74 | import io.protostuff.jetbrains.plugin.psi.MapNode; |
34 | | -import io.protostuff.jetbrains.plugin.psi.MessageNameNode; |
35 | 75 | import io.protostuff.jetbrains.plugin.psi.MessageNode; |
36 | 76 | import io.protostuff.jetbrains.plugin.psi.OneOfNode; |
37 | | -import io.protostuff.jetbrains.plugin.psi.OneofFieldNode; |
38 | 77 | import io.protostuff.jetbrains.plugin.psi.OptionEntryNode; |
39 | 78 | import io.protostuff.jetbrains.plugin.psi.OptionNode; |
40 | 79 | import io.protostuff.jetbrains.plugin.psi.OptionValueNode; |
|
50 | 89 | import io.protostuff.jetbrains.plugin.psi.StandardFieldReferenceNode; |
51 | 90 | import io.protostuff.jetbrains.plugin.psi.SyntaxStatement; |
52 | 91 | import io.protostuff.jetbrains.plugin.psi.TypeReferenceNode; |
| 92 | +import java.lang.reflect.Method; |
| 93 | +import java.util.Collections; |
53 | 94 | import java.util.HashMap; |
54 | 95 | import java.util.List; |
55 | 96 | import java.util.Map; |
|
71 | 112 | */ |
72 | 113 | public class ProtoParserDefinition implements ParserDefinition { |
73 | 114 |
|
| 115 | + private static final Logger LOGGER = Logger.getInstance(ProtoParserDefinition.class); |
| 116 | + |
74 | 117 | public static final PsiElementTypeFactory ELEMENT_FACTORY = PsiElementTypeFactory.create(ProtoLanguage.INSTANCE, new ProtoParser(null)); |
75 | 118 | public static final TokenSet KEYWORDS = ELEMENT_FACTORY.createTokenSet( |
76 | 119 | ProtoLexer.PACKAGE, |
@@ -218,51 +261,70 @@ public class ProtoParserDefinition implements ParserDefinition { |
218 | 261 | public static final TokenIElementType ASSIGN = TOKEN_TYPES.get(ProtoLexer.ASSIGN); |
219 | 262 | private static final List<RuleIElementType> RULE_TYPES = ELEMENT_FACTORY.getRuleIElementTypes(); |
220 | 263 | // Rules |
221 | | - public static final IElementType R_TYPE_REFERENCE = RULE_TYPES.get(ProtoParser.RULE_typeReference); |
222 | | - public static final IElementType R_NAME = RULE_TYPES.get(ProtoParser.RULE_ident); |
223 | | - public static final IElementType R_FIELD_MODIFIER = RULE_TYPES.get(ProtoParser.RULE_fieldModifier); |
224 | | - public static final IElementType R_FIELD_NAME = RULE_TYPES.get(ProtoParser.RULE_fieldName); |
225 | | - public static final IElementType R_TAG = RULE_TYPES.get(ProtoParser.RULE_tag); |
| 264 | + public static final IElementType R_TYPE_REFERENCE = RULE_TYPES.get(RULE_typeReference); |
| 265 | + public static final IElementType R_NAME = RULE_TYPES.get(RULE_ident); |
| 266 | + public static final IElementType R_FIELD_MODIFIER = RULE_TYPES.get(RULE_fieldModifier); |
| 267 | + public static final IElementType R_FIELD_NAME = RULE_TYPES.get(RULE_fieldName); |
| 268 | + public static final IElementType R_TAG = RULE_TYPES.get(RULE_tag); |
226 | 269 | private static final IFileElementType FILE = new IFileElementType(ProtoLanguage.INSTANCE); |
227 | 270 | private static final TokenSet COMMENTS = ELEMENT_FACTORY.createTokenSet(COMMENT, LINE_COMMENT); |
228 | 271 | private static final TokenSet STRING = ELEMENT_FACTORY.createTokenSet(STRING_VALUE); |
229 | 272 | private final Map<Integer, Function<ASTNode, AntlrPsiNode>> elementFactories = new HashMap<>(); |
230 | 273 |
|
| 274 | + private final Map<String, Method> parserRuleMethods = createParserRuleMethods(); |
| 275 | + |
231 | 276 | /** |
232 | 277 | * Create new parser definition. |
233 | 278 | */ |
234 | 279 | public ProtoParserDefinition() { |
235 | | - register(ProtoParser.RULE_syntaxStatement, SyntaxStatement::new); |
236 | | - register(ProtoParser.RULE_packageStatement, PackageStatement::new); |
237 | | - register(ProtoParser.RULE_importStatement, ImportNode::new); |
238 | | - register(ProtoParser.RULE_fileReference, FileReferenceNode::new); |
239 | | - register(ProtoParser.RULE_messageBlock, MessageNode::new); |
240 | | - register(ProtoParser.RULE_messageName, MessageNameNode::new); |
241 | | - register(ProtoParser.RULE_field, FieldNode::new); |
242 | | - register(ProtoParser.RULE_typeReference, TypeReferenceNode::new); |
243 | | - register(ProtoParser.RULE_groupBlock, GroupNode::new); |
244 | | - register(ProtoParser.RULE_enumBlock, EnumNode::new); |
245 | | - register(ProtoParser.RULE_enumField, EnumConstantNode::new); |
246 | | - register(ProtoParser.RULE_serviceBlock, ServiceNode::new); |
247 | | - register(ProtoParser.RULE_rpcMethod, RpcMethodNode::new); |
248 | | - register(ProtoParser.RULE_optionEntry, OptionEntryNode::new); |
249 | | - register(ProtoParser.RULE_option, OptionNode::new); |
250 | | - register(ProtoParser.RULE_fieldRerefence, FieldReferenceNode::new); |
251 | | - register(ProtoParser.RULE_standardFieldRerefence, StandardFieldReferenceNode::new); |
252 | | - register(ProtoParser.RULE_customFieldReference, CustomFieldReferenceNode::new); |
253 | | - register(ProtoParser.RULE_optionValue, OptionValueNode::new); |
254 | | - register(ProtoParser.RULE_oneof, OneOfNode::new); |
255 | | - register(ProtoParser.RULE_oneofField, OneofFieldNode::new); |
256 | | - register(ProtoParser.RULE_extendBlock, ExtendNode::new); |
257 | | - register(ProtoParser.RULE_extendBlockEntry, ExtendEntryNode::new); |
258 | | - register(ProtoParser.RULE_extensions, ExtensionsNode::new); |
259 | | - register(ProtoParser.RULE_map, MapNode::new); |
260 | | - register(ProtoParser.RULE_mapKey, MapKeyNode::new); |
261 | | - register(ProtoParser.RULE_range, RangeNode::new); |
262 | | - register(ProtoParser.RULE_reservedFieldRanges, ReservedFieldRangesNode::new); |
263 | | - register(ProtoParser.RULE_reservedFieldNames, ReservedFieldNamesNode::new); |
264 | | - register(ProtoParser.RULE_rpcType, RpcMethodTypeNode::new); |
265 | | - register(ProtoParser.RULE_proto, ProtoRootNode::new); |
| 280 | + register(RULE_customFieldReference, CustomFieldReferenceNode::new); |
| 281 | + register(RULE_enumBlock, EnumNode::new); |
| 282 | + register(RULE_enumField, EnumConstantNode::new); |
| 283 | + register(RULE_enumName, GenericNameNode::new); |
| 284 | + register(RULE_extendBlock, ExtendNode::new); |
| 285 | + register(RULE_extendBlockEntry, ExtendEntryNode::new); |
| 286 | + register(RULE_extensions, ExtensionsNode::new); |
| 287 | + register(RULE_field, FieldNode::new); |
| 288 | + register(RULE_fieldName, GenericNameNode::new); |
| 289 | + register(RULE_fieldRerefence, FieldReferenceNode::new); |
| 290 | + register(RULE_fileReference, FileReferenceNode::new); |
| 291 | + register(RULE_groupBlock, GroupNode::new); |
| 292 | + register(RULE_importStatement, ImportNode::new); |
| 293 | + register(RULE_map, MapNode::new); |
| 294 | + register(RULE_mapKey, MapKeyNode::new); |
| 295 | + register(RULE_messageBlock, MessageNode::new); |
| 296 | + register(RULE_messageName, GenericNameNode::new); |
| 297 | + register(RULE_oneof, OneOfNode::new); |
| 298 | + register(RULE_oneofName, GenericNameNode::new); |
| 299 | + register(RULE_option, OptionNode::new); |
| 300 | + register(RULE_optionEntry, OptionEntryNode::new); |
| 301 | + register(RULE_optionValue, OptionValueNode::new); |
| 302 | + register(RULE_packageStatement, PackageStatement::new); |
| 303 | + register(RULE_proto, ProtoRootNode::new); |
| 304 | + register(RULE_range, RangeNode::new); |
| 305 | + register(RULE_reservedFieldNames, ReservedFieldNamesNode::new); |
| 306 | + register(RULE_reservedFieldRanges, ReservedFieldRangesNode::new); |
| 307 | + register(RULE_rpcMethod, RpcMethodNode::new); |
| 308 | + register(RULE_rpcType, RpcMethodTypeNode::new); |
| 309 | + register(RULE_rpcName, GenericNameNode::new); |
| 310 | + register(RULE_serviceBlock, ServiceNode::new); |
| 311 | + register(RULE_serviceName, GenericNameNode::new); |
| 312 | + register(RULE_standardFieldRerefence, StandardFieldReferenceNode::new); |
| 313 | + register(RULE_typeReference, TypeReferenceNode::new); |
| 314 | + register(RULE_syntaxStatement, SyntaxStatement::new); |
| 315 | + } |
| 316 | + |
| 317 | + private Map<String, Method> createParserRuleMethods() { |
| 318 | + Map<String, Method> result = new HashMap<>(); |
| 319 | + for (String ruleName : ruleNames) { |
| 320 | + try { |
| 321 | + Method method = ProtoParser.class.getMethod(ruleName); |
| 322 | + result.put(ruleName, method); |
| 323 | + } catch (NoSuchMethodException e) { |
| 324 | + LOGGER.error("Could not get parser method for rule " + ruleName); |
| 325 | + } |
| 326 | + } |
| 327 | + return Collections.unmodifiableMap(result); |
266 | 328 | } |
267 | 329 |
|
268 | 330 | public static TokenIElementType token(int token) { |
@@ -294,22 +356,33 @@ public PsiParser createParser(Project project) { |
294 | 356 | @Override |
295 | 357 | protected ParseTree parse(Parser parser, IElementType root) { |
296 | 358 | // start rule depends on root passed in; sometimes we want to create an ID node etc... |
| 359 | + ProtoParser protoParser = (ProtoParser) parser; |
297 | 360 | if (root instanceof IFileElementType) { |
298 | | - return ((ProtoParser) parser).proto(); |
| 361 | + return protoParser.proto(); |
299 | 362 | } |
300 | 363 | if (root instanceof RuleIElementType) { |
301 | 364 | RuleIElementType type = (RuleIElementType) root; |
302 | | - if (ProtoParserDefinition.rule(ProtoParser.RULE_fileReference).equals(type)) { |
303 | | - return ((ProtoParser) parser).fileReference(); |
304 | | - } |
| 365 | + String ruleName = ruleNames[type.getRuleIndex()]; |
| 366 | + return parserRule(protoParser, ruleName); |
305 | 367 | } |
306 | | - // let's hope it's an ID as needed by "rename function" |
307 | | - throw new UnsupportedOperationException(); |
308 | | - // return ((ProtoParser) parser).name(); |
| 368 | + throw new UnsupportedOperationException(String.valueOf(root.getIndex())); |
309 | 369 | } |
310 | 370 | }; |
311 | 371 | } |
312 | 372 |
|
| 373 | + @NotNull |
| 374 | + private ParseTree parserRule(ProtoParser protoParser, String ruleName) { |
| 375 | + try { |
| 376 | + Method method = parserRuleMethods.get(ruleName); |
| 377 | + if (method == null) { |
| 378 | + throw new IllegalStateException("Not a parser rule: " + ruleName); |
| 379 | + } |
| 380 | + return (ParseTree) method.invoke(protoParser); |
| 381 | + } catch (Exception e) { |
| 382 | + throw new IllegalStateException("Exception in parser rule: " + ruleName, e); |
| 383 | + } |
| 384 | + } |
| 385 | + |
313 | 386 | @Override |
314 | 387 | public IFileElementType getFileNodeType() { |
315 | 388 | return FILE; |
|
0 commit comments