1 /*
2  *   Copyright (c) 2021 Jan Dolinár
3  *
4  *   This source code is released for free distribution under the terms of the
5  *   GNU General Public License version 2 or (at your option) any later version.
6  *
7  *   This module contains functions to generate tags for Kotlin.
8  */
9 
10 /*
11 *   INCLUDE FILES
12 */
13 #include "parse.h"
14 #include "trace.h"
15 
16 /*
17 * FUNCTION DEFINITIONS
18 */
getcFromKotlinFile(struct parserCtx * auxil)19 static int getcFromKotlinFile(struct parserCtx *auxil)
20 {
21     int c = getcFromInputFile();
22     if (auxil->parenthesis_level > 0 && (c == '\r' || c == '\n'))
23     {
24         return ' ';
25     }
26     return c;
27 }
28 
makeKotlinTag(struct parserCtx * auxil,const char * name,long offset,bool pushScope)29 static void makeKotlinTag (struct parserCtx *auxil, const char *name, long offset, bool pushScope)
30 {
31     int k = PEEK_KIND(auxil);
32     if (k == K_IGNORE) return;
33     tagEntryInfo e;
34     if (*name != '`')
35     {
36         initTagEntry(&e, name, k);
37     } else
38     {
39         size_t len = strlen(name);
40         Assert(len >= 2);
41         len -= 2;
42         vString *stripped = vStringNewNInit(name + 1, len);
43         initTagEntry(&e, vStringValue(stripped), k);
44         vStringDelete(stripped);
45     }
46     e.lineNumber = getInputLineNumberForFileOffset (offset);
47     e.filePosition = getInputFilePositionForLine (e.lineNumber);
48     e.extensionFields.scopeIndex = BASE_SCOPE(auxil);
49     int scope_index = makeTagEntry (&e);
50     if (pushScope)
51     {
52         SET_SCOPE(auxil, scope_index);
53     }
54 }
55 
56 #ifdef DEBUG
reportFailure(struct parserCtx * auxil,long offset)57 static void reportFailure(struct parserCtx *auxil, long offset)
58 {
59     if(auxil->fail_offset < 0)
60     {
61         auxil->fail_offset = offset;
62     }
63 }
64 
resetFailure(struct parserCtx * auxil,long offset)65 static void resetFailure(struct parserCtx *auxil, long offset)
66 {
67     if(auxil->fail_offset >= 0)
68     {
69         unsigned long startLine = getInputLineNumberForFileOffset(auxil->fail_offset);
70         unsigned long endLine = getInputLineNumberForFileOffset(offset-1);
71         if (startLine == endLine)
72         {
73             TRACE_PRINT("Failed to parse '%s' at line %lu!\n", getInputFileName(), startLine);
74         } else
75         {
76             TRACE_PRINT("Failed to parse '%s' from line %lu to line %lu!\n", getInputFileName(), startLine, endLine);
77         }
78     }
79     auxil->fail_offset = -1;
80 }
81 #endif
82 
ctxInit(struct parserCtx * auxil)83 static void ctxInit (struct parserCtx *auxil)
84 {
85     BASE_INIT(auxil, K_INTERFACE);
86     auxil->parenthesis_level = 0;
87     #ifdef DEBUG
88     auxil->fail_offset = -1;
89     #endif
90 }
91 
ctxFini(struct parserCtx * auxil)92 static void ctxFini (struct parserCtx *auxil)
93 {
94     BASE_FINI(auxil);
95 }
96 
findKotlinTags(void)97 static void findKotlinTags (void)
98 {
99     struct parserCtx auxil;
100 
101     ctxInit (&auxil);
102     pkotlin_context_t *pctx = pkotlin_create(&auxil);
103 
104     while (pkotlin_parse(pctx, NULL) && (!BASE_ERROR(&auxil)) );
105 
106     pkotlin_destroy(pctx);
107     ctxFini (&auxil);
108 }
109 
KotlinParser(void)110 extern parserDefinition* KotlinParser (void)
111 {
112     static const char *const extensions [] = { "kt", "kts", NULL };
113     parserDefinition* def = parserNew ("Kotlin");
114     def->kindTable = KotlinKinds;
115     def->kindCount = ARRAY_SIZE (KotlinKinds);
116     def->extensions = extensions;
117     def->parser = findKotlinTags;
118     def->useCork = true;
119     def->requestAutomaticFQTag = true;
120     def->defaultScopeSeparator = ".";
121     def->enabled = true;
122     return def;
123 }
124