1717package  org .intellij .grammar .generator ;
1818
1919import  com .intellij .openapi .diagnostic .Logger ;
20- import  com .intellij .openapi .util .Couple ;
2120import  com .intellij .openapi .util .Pair ;
21+ import  com .intellij .openapi .util .Trinity ;
2222import  com .intellij .openapi .util .io .FileUtil ;
2323import  com .intellij .openapi .util .text .StringUtil ;
2424import  com .intellij .psi .CommonClassNames ;
@@ -1348,17 +1348,26 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
13481348      imports .add (PSI_ELEMENT_CLASS );
13491349      imports .add (AST_NODE_CLASS );
13501350    }
1351-     Map <String , Couple <String >> compositeToClassAndFactoryMap  = new  THashMap <>();
1351+     boolean  useExactElements  = "all" .equals (G .generateExactTypes ) || G .generateExactTypes .contains ("elements" );
1352+     boolean  useExactStubs  = G .generateExactTypes .contains ("stubs" );
1353+     boolean  useExactTokens  = "all" .equals (G .generateExactTypes ) || G .generateExactTypes .contains ("tokens" );
1354+ 
1355+     Map <String , Trinity <String , String , RuleInfo >> compositeToClassAndFactoryMap  = new  THashMap <>();
13521356    for  (String  elementType  : sortedCompositeTypes .keySet ()) {
13531357      BnfRule  rule  = sortedCompositeTypes .get (elementType );
1358+       RuleInfo  ruleInfo  = ruleInfo (rule );
13541359      String  elementTypeClass  = getAttribute (rule , KnownAttribute .ELEMENT_TYPE_CLASS );
13551360      String  elementTypeFactory  = getAttribute (rule , KnownAttribute .ELEMENT_TYPE_FACTORY );
1356-       compositeToClassAndFactoryMap .put (elementType , Couple . of (elementTypeClass , elementTypeFactory ));
1361+       compositeToClassAndFactoryMap .put (elementType , Trinity . create (elementTypeClass , elementTypeFactory ,  ruleInfo ));
13571362      if  (elementTypeFactory  != null ) {
13581363        imports .add (StringUtil .getPackageName (elementTypeFactory ));
13591364      }
13601365      else  {
13611366        ContainerUtil .addIfNotNull (imports , elementTypeClass );
1367+         if  (useExactStubs  && ruleInfo .stub  != null ) {
1368+           imports .add (ISTUBELEMENTTYPE_CLASS );
1369+           imports .add (ruleInfo .intfClass );
1370+         }
13621371      }
13631372    }
13641373    if  (tokenTypeFactory  != null ) {
@@ -1384,28 +1393,35 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
13841393    generateClassHeader (className , imports , "" , Java .INTERFACE );
13851394    if  (G .generateElementTypes ) {
13861395      for  (String  elementType  : sortedCompositeTypes .keySet ()) {
1387-         Couple <String > pair  = compositeToClassAndFactoryMap .get (elementType );
1396+         String  exactType  = null ;
1397+         Trinity <String , String , RuleInfo > info  = compositeToClassAndFactoryMap .get (elementType );
13881398        String  elementCreateCall ;
1389-         if  (pair .second  == null ) {
1390-           elementCreateCall  = "new "  + StringUtil . getShortName ( pair .first );
1399+         if  (info .second  == null ) {
1400+           elementCreateCall  = "new "  + ( exactType  =  myShortener . fun ( info .first ) );
13911401        }
13921402        else  {
1393-           elementCreateCall  = myShortener .fun (StringUtil .getPackageName (pair .second )) + "."  + StringUtil .getShortName (pair .second );
1403+           elementCreateCall  = myShortener .fun (StringUtil .getPackageName (info .second )) + "."  + StringUtil .getShortName (info .second );
13941404        }
1405+         String  fieldType  = ObjectUtils .notNull (
1406+           useExactElements  ? exactType  :
1407+           useExactStubs  && info .third .stub  != null  ? "IStubElementType<?, "  + myShortener .fun (info .third .intfClass ) + ">"  :
1408+           "IElementType" );
13951409        String  callFix  = elementCreateCall .equals ("new IElementType" ) ? ", null"  : "" ;
1396-         out ("IElementType  "elementType  + " = "  + elementCreateCall  + "(\" "  + elementType  + "\" "  + callFix  + ");" );
1410+         out (fieldType  +  "  "elementType  + " = "  + elementCreateCall  + "(\" "  + elementType  + "\" "  + callFix  + ");" );
13971411      }
13981412    }
13991413    if  (G .generateTokenTypes ) {
14001414      newLine ();
1415+       String  exactType  = null ;
14011416      Map <String , String > sortedTokens  = ContainerUtil .newTreeMap ();
14021417      String  tokenCreateCall ;
14031418      if  (tokenTypeFactory  == null ) {
1404-         tokenCreateCall  = "new "  + StringUtil . getShortName (tokenTypeClass );
1419+         tokenCreateCall  = "new "  + ( exactType  =  myShortener . fun (tokenTypeClass ) );
14051420      }
14061421      else  {
14071422        tokenCreateCall  = myShortener .fun (StringUtil .getPackageName (tokenTypeFactory )) + "."  + StringUtil .getShortName (tokenTypeFactory );
14081423      }
1424+       String  fieldType  = ObjectUtils .notNull (useExactTokens  ? exactType  : null , "IElementType" );
14091425      for  (String  tokenText  : mySimpleTokens .keySet ()) {
14101426        String  tokenName  = ObjectUtils .chooseNotNull (mySimpleTokens .get (tokenText ), tokenText );
14111427        if  (isIgnoredWhitespaceToken (tokenName , tokenText )) continue ;
@@ -1414,7 +1430,7 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
14141430      for  (String  tokenType  : sortedTokens .keySet ()) {
14151431        String  callFix  = tokenCreateCall .equals ("new IElementType" ) ? ", null"  : "" ;
14161432        String  tokenString  = sortedTokens .get (tokenType );
1417-         out ("IElementType  "tokenType  + " = "  + tokenCreateCall  + "(\" "  + StringUtil .escapeStringCharacters (tokenString ) + "\" " +callFix +");" );
1433+         out (fieldType  +  "  "tokenType  + " = "  + tokenCreateCall  + "(\" "  + StringUtil .escapeStringCharacters (tokenString ) + "\" " +callFix +");" );
14181434      }
14191435    }
14201436    if  (G .generatePsi  && G .generatePsiClassesMap ) {
0 commit comments