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