Skip to content

Commit 3d6983e

Browse files
committed
#16 Autocomple and documentation provider for fields
1 parent ba6516b commit 3d6983e

File tree

10 files changed

+209
-15
lines changed

10 files changed

+209
-15
lines changed

src/main/java/com/bloxbean/algodea/idea/common/AlgoIcons.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public class AlgoIcons {
3131
public final static Icon TEAL_FILE_ICON = IconLoader.getIcon("/icons/teal_file.png", AlgoIcons.class);
3232
public final static Icon MODULE_ICON = IconLoader.getIcon("/icons/module.png", AlgoIcons.class);
3333
public final static Icon OPCODE_ICON = IconLoader.getIcon("/icons/opcode.png", AlgoIcons.class);
34-
public static final Icon FIELD_ICON = IconLoader.getIcon("/icons/field.png", AlgoIcons.class);;
34+
public static final Icon FIELD_ICON = IconLoader.getIcon("/icons/field.png", AlgoIcons.class);
35+
public static final Icon NAMED_INT_CONSTANT_ICON = IconLoader.getIcon("/icons/constant.png ", AlgoIcons.class);
3536
public static final Icon LSIG_FILE_ICON = IconLoader.getIcon("/icons/lsig_file.png", AlgoIcons.class);
3637
public static final Icon TOK_FILE_ICON = IconLoader.getIcon("/icons/tok_file.png", AlgoIcons.class);
3738
public static final Icon ALGO_TX_ICON = IconLoader.getIcon("/icons/algo_tx.png", AlgoIcons.class);

src/main/java/com/bloxbean/algodea/idea/language/completion/metadata/atoms/TEALKeywords.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
package com.bloxbean.algodea.idea.language.completion.metadata.atoms;
2424

25+
import com.bloxbean.algodea.idea.language.completion.metadata.elements.TEALConstantElement;
2526
import com.bloxbean.algodea.idea.language.completion.metadata.elements.TEALFieldElement;
2627
import com.bloxbean.algodea.idea.language.completion.metadata.elements.TEALKeywordElement;
2728
import com.bloxbean.algodea.idea.language.opcode.TEALOpCodeFactory;
@@ -132,8 +133,8 @@ public final class TEALKeywords {
132133
public static final List<LookupElement> TYPEENUM_CONSTANT_ELEMENTS = TEALOpCodeFactory.getInstance()
133134
.getFields(TYPE_ENUM_MAPPING)
134135
.stream()
135-
.map(f -> new TEALFieldElement(f))
136-
.map(TEALFieldElement::getLookupElement)
136+
.map(f -> new TEALConstantElement(f))
137+
.map(TEALConstantElement::getLookupElement)
137138
.collect(Collectors.toList());
138139

139140
public static final List<LookupElement> GLOBAL_FIELDS_ELEMENTS = TEALOpCodeFactory.getInstance()
@@ -160,8 +161,8 @@ public final class TEALKeywords {
160161
public static final List<LookupElement> ONCOMPLETE_CONSTANT_ELEMENTS = TEALOpCodeFactory.getInstance()
161162
.getFields(ONCOMPLETE_CONSTANTS)
162163
.stream()
163-
.map(f -> new TEALFieldElement(f))
164-
.map(TEALFieldElement::getLookupElement)
164+
.map(f -> new TEALConstantElement(f))
165+
.map(TEALConstantElement::getLookupElement)
165166
.collect(Collectors.toList());
166167

167168

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2020 BloxBean Project
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
package com.bloxbean.algodea.idea.language.completion.metadata.elements;
24+
25+
import com.bloxbean.algodea.idea.common.AlgoIcons;
26+
import com.bloxbean.algodea.idea.language.opcode.model.Field;
27+
import com.intellij.codeInsight.lookup.LookupElement;
28+
import com.intellij.codeInsight.lookup.LookupElementBuilder;
29+
import com.intellij.openapi.diagnostic.Logger;
30+
31+
public class TEALConstantElement implements TEALElement {
32+
private final static Logger LOG = Logger.getInstance(TEALConstantElement.class);
33+
34+
private final Field field;
35+
36+
public TEALConstantElement(Field field) {
37+
this.field = field;
38+
}
39+
40+
@Override
41+
public LookupElement getLookupElement() {
42+
if(field == null)
43+
return null;
44+
45+
if(LOG.isDebugEnabled()) {
46+
if (field.getName() == null) {
47+
LOG.error("Field.getName() cannot be null" + field);
48+
}
49+
}
50+
return LookupElementBuilder
51+
.create(field.getName())
52+
.withIcon(AlgoIcons.NAMED_INT_CONSTANT_ICON)
53+
.withTypeText(field.getType());
54+
55+
}
56+
57+
public LookupElement getCompositeLookupElement(String prefix, String suffix) {
58+
59+
if(field == null)
60+
return null;
61+
62+
if(LOG.isDebugEnabled()) {
63+
if (field.getName() == null) {
64+
LOG.error("Field.getName() cannot be null" + field);
65+
}
66+
}
67+
68+
StringBuilder sb = new StringBuilder();
69+
70+
if(prefix != null) {
71+
sb.append(prefix)
72+
.append(" ");
73+
}
74+
75+
sb.append(field.getName());
76+
77+
if(suffix != null)
78+
sb.append(" ")
79+
.append(suffix);
80+
81+
return LookupElementBuilder
82+
.create(sb.toString())
83+
.withIcon(AlgoIcons.NAMED_INT_CONSTANT_ICON);
84+
85+
}
86+
}

src/main/java/com/bloxbean/algodea/idea/language/completion/providers/NamedIntegerConstantsCompletionProvider.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters,
5050
@NotNull CompletionResultSet result) {
5151
result.addAllElements(TEALKeywords.ONCOMPLETE_CONSTANT_ELEMENTS);
5252
result.addAllElements(TEALKeywords.TYPEENUM_CONSTANT_ELEMENTS);
53+
5354
result.stopHere();
5455
}
5556
}

src/main/java/com/bloxbean/algodea/idea/language/documentation/TEALDocumentationProvider.java

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package com.bloxbean.algodea.idea.language.documentation;
2424

2525
import com.bloxbean.algodea.idea.language.completion.metadata.atoms.TEALKeywords;
26+
import com.bloxbean.algodea.idea.language.opcode.model.Field;
2627
import com.bloxbean.algodea.idea.language.opcode.model.OpCode;
2728
import com.bloxbean.algodea.idea.language.opcode.TEALOpCodeFactory;
2829
import com.bloxbean.algodea.idea.language.psi.TEALTypes;
@@ -48,8 +49,20 @@ public class TEALDocumentationProvider extends AbstractDocumentationProvider {
4849
TEALTypes.TXN_LOADING_OP,
4950
TEALTypes.FLOWCONTROL_OP,
5051
TEALTypes.STATEACCESS_OP,
51-
TEALTypes.PSEUDO_OP
52+
TEALTypes.PSEUDO_OP,
53+
TEALTypes.NAMED_INTEGER_CONSTANT,
54+
TEALTypes.TYPENUM_CONSTANT,
55+
TEALTypes.GLOBAL_FIELD,
56+
TEALTypes.TXN_FIELD_ARG,
57+
TEALTypes.ASSET_PARAMS_GET_FIELD,
58+
TEALTypes.ASSET_HOLDING_GET_FIELD
5259
);
60+
public static final String ONCOMPLETE = "oncomplete";
61+
public static final String TYPEENUM_CONSTANTS = "typeenum_constants";
62+
public static final String GLOBAL_FIELDS = "global_fields";
63+
public static final String TXN_FIELDS = "txn_fields";
64+
public static final String ASSET_PARAMS_GET_FIELDS = "asset_params_get_fields";
65+
public static final String ASSET_HOLDING_GET_FIELDS = "asset_holding_get_fields";
5366

5467
static {
5568
SEARCH_TYPES.addAll(GENERAL_OPERATIONS_ELEMENTS);
@@ -73,9 +86,15 @@ public String getQuickNavigateInfo(PsiElement element, PsiElement originalElemen
7386
@Nullable
7487
@Override
7588
public String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
76-
Optional<String> opcodeDocumentation = loadingOpcodeDocumentation(element);
77-
if (opcodeDocumentation.isPresent()) {
78-
return opcodeDocumentation.get();
89+
Optional<String> documentation = loadingOpcodeDocumentation(element);
90+
if (documentation.isPresent()) {
91+
return documentation.get();
92+
}
93+
94+
//Check if Named Integer Constant or TypeEnum Constant
95+
documentation = loadFieldDocumentation(element);
96+
if(documentation.isPresent()) {
97+
return documentation.get();
7998
}
8099

81100
return null;
@@ -105,6 +124,44 @@ private Optional<String> loadingOpcodeDocumentation(PsiElement element) {
105124
return Optional.empty();
106125
}
107126

127+
private Optional<String> loadFieldDocumentation(PsiElement element) {
128+
if(element == null) return Optional.empty();
129+
130+
if (TEALTypes.NAMED_INTEGER_CONSTANT.equals(element.getNode().getElementType())) {
131+
String value = element.getNode().getText();
132+
Field field = TEALOpCodeFactory.getInstance().getField(ONCOMPLETE, value);
133+
if(field != null)
134+
return field.formatHtml();
135+
} else if(TEALTypes.TYPENUM_CONSTANT.equals(element.getNode().getElementType())) {
136+
String value = element.getNode().getText();
137+
Field field = TEALOpCodeFactory.getInstance().getField(TYPEENUM_CONSTANTS, value);
138+
if(field != null)
139+
return field.formatHtml();
140+
} else if(TEALTypes.GLOBAL_FIELD.equals(element.getNode().getElementType())) {
141+
String value = element.getNode().getText();
142+
Field field = TEALOpCodeFactory.getInstance().getField(GLOBAL_FIELDS, value);
143+
if(field != null)
144+
return field.formatHtml();
145+
} else if(TEALTypes.TXN_FIELD_ARG.equals(element.getNode().getElementType())) {
146+
String value = element.getNode().getText();
147+
Field field = TEALOpCodeFactory.getInstance().getField(TXN_FIELDS, value);
148+
if(field != null)
149+
return field.formatHtml();
150+
} else if(TEALTypes.ASSET_PARAMS_GET_FIELD.equals(element.getNode().getElementType())) {
151+
String value = element.getNode().getText();
152+
Field field = TEALOpCodeFactory.getInstance().getField(ASSET_PARAMS_GET_FIELDS, value);
153+
if(field != null)
154+
return field.formatHtml();
155+
} else if(TEALTypes.ASSET_HOLDING_GET_FIELD.equals(element.getNode().getElementType())) {
156+
String value = element.getNode().getText();
157+
Field field = TEALOpCodeFactory.getInstance().getField(ASSET_HOLDING_GET_FIELDS, value);
158+
if(field != null)
159+
return field.formatHtml();
160+
}
161+
162+
return Optional.empty();
163+
}
164+
108165
private Optional<String> getDocumentHtmlForKey(String nodeText) {
109166
OpCode opCode = TEALOpCodeFactory.getInstance().getOpCode(nodeText);
110167
if (opCode == null)

src/main/java/com/bloxbean/algodea/idea/language/opcode/TEALOpCodeFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.fasterxml.jackson.core.type.TypeReference;
2929
import com.fasterxml.jackson.databind.ObjectMapper;
3030
import com.intellij.openapi.diagnostic.Logger;
31+
import com.intellij.openapi.util.text.StringUtil;
3132

3233
import java.net.URL;
3334
import java.util.*;
@@ -134,4 +135,13 @@ public Collection<Field> getFields(String type) {
134135
return typeFields.values();
135136
}
136137

138+
public Field getField(String type, String fieldText) {
139+
if(StringUtil.isEmpty(fieldText)) return null;
140+
141+
Map<String, Field> typeFields = fields.get(type);
142+
if(typeFields == null) return null;
143+
144+
return typeFields.get(fieldText);
145+
}
146+
137147
}

src/main/java/com/bloxbean/algodea/idea/language/opcode/model/Field.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.bloxbean.algodea.idea.language.opcode.model;
22

33
import java.util.Objects;
4+
import java.util.Optional;
45

56
public class Field {
67
private int index;
@@ -80,4 +81,40 @@ public String toString() {
8081
", desc='" + desc + '\'' +
8182
'}';
8283
}
84+
85+
public Optional<String> formatHtml() {
86+
StringBuilder sb = new StringBuilder();
87+
sb.append("<ul>");
88+
89+
//createLiTag(sb, "Value", String.valueOf(index));
90+
91+
if(name != null) {
92+
createLiTag(sb, "Name", name);
93+
}
94+
95+
if(type != null && !type.isEmpty()) {
96+
createLiTag(sb, "Type", type);
97+
}
98+
99+
if(desc != null && !desc.isEmpty()) {
100+
createLiTag(sb, null, desc);
101+
}
102+
103+
if(note != null && !note.isEmpty()) {
104+
createLiTag(sb, null, note);
105+
}
106+
107+
return Optional.of(sb.toString());
108+
}
109+
110+
private void createLiTag(StringBuilder sb, String key, String value) {
111+
sb.append("<li>");
112+
if(key != null) {
113+
sb.append(key);
114+
sb.append(": ");
115+
}
116+
sb.append(value);
117+
sb.append("</li>");
118+
}
119+
83120
}

src/main/resources/icons/constant.png

1.25 KB
Loading
Lines changed: 1 addition & 0 deletions
Loading

src/main/resources/opcodes/fields.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,37 +294,37 @@
294294
"index": 0,
295295
"name": "NoOp",
296296
"type": "NoOp",
297-
"desc": "NoOp"
297+
"desc": "Only execute the ApprovalProgram associated with this application ID, with no additional effects."
298298
},
299299
{
300300
"index": 1,
301301
"name": "OptIn",
302302
"type": "OptIn",
303-
"desc": "OptIn"
303+
"desc": "Before executing the ApprovalProgram, allocate local state for this application into the sender's account data."
304304
},
305305
{
306306
"index": 2,
307307
"name": "CloseOut",
308308
"type": "CloseOut",
309-
"desc": "CloseOut"
309+
"desc": "After executing the ApprovalProgram, clear any local state for this application out of the sender's account data."
310310
},
311311
{
312312
"index": 3,
313313
"name": "ClearState",
314314
"type": "ClearState",
315-
"desc": "ClearState"
315+
"desc": "Don't execute the ApprovalProgram, and instead execute the ClearStateProgram (which may not reject this transaction). Additionally, clear any local state for this application out of the sender's account data as in CloseOutOC."
316316
},
317317
{
318318
"index": 4,
319319
"name": "UpdateApplication",
320320
"type": "UpdateApplication",
321-
"desc": "UpdateApplication"
321+
"desc": "After executing the ApprovalProgram, replace the ApprovalProgram and ClearStateProgram associated with this application ID with the programs specified in this transaction."
322322
},
323323
{
324324
"index": 5,
325325
"name": "DeleteApplication",
326326
"type": "DeleteApplication",
327-
"desc": "DeleteApplication"
327+
"desc": "After executing the ApprovalProgram, delete the application parameters from the account data of the application's creator."
328328
}
329329
],
330330
"typeenum_constants": [

0 commit comments

Comments
 (0)