diff --git a/.gitattributes b/.gitattributes index fb1d555..2106964 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1 @@ -src/main/java/org/vyperlang/plugin/grammar/**/*.java linguist-generated=true -src/main/java/org/vyperlang/plugin/parser/**/*.java linguist-generated=true -src/main/java/org/vyperlang/plugin/psi/**/*.java linguist-generated=true +src/gen/**/*.* linguist-generated=true diff --git a/.idea/modules/vyper-plugin.main.iml b/.idea/modules/vyper-plugin.main.iml index 00eb738..f254a0a 100644 --- a/.idea/modules/vyper-plugin.main.iml +++ b/.idea/modules/vyper-plugin.main.iml @@ -39,7 +39,7 @@ - + diff --git a/CHANGELOG.md b/CHANGELOG.md index e0bbb69..aba2b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ## [Unreleased] - Fix auto-complete issues and `immutable` support ([#31](https://github.com/NikitaMishin/vyper-plugin/issues/31)) +- Fix find usages issues ([#28](https://github.com/NikitaMishin/vyper-plugin/issues/28)) for `immutable`, `interface` and `struct` ## [0.2.0-alpha.3] - 2024-07-02 - Add automatic compilation errors ([#36](https://github.com/NikitaMishin/vyper-plugin/issues/36)) diff --git a/src/main/gen/org/vyperlang/plugin/parser/BaseVyperParser.java b/src/main/gen/org/vyperlang/plugin/parser/BaseVyperParser.java index baed1a2..b7bbe71 100644 --- a/src/main/gen/org/vyperlang/plugin/parser/BaseVyperParser.java +++ b/src/main/gen/org/vyperlang/plugin/parser/BaseVyperParser.java @@ -1986,7 +1986,7 @@ private static boolean ImmutableType_1_5(PsiBuilder b, int l) { } /* ********************************************************** */ - // implements &INDNONE ':' &INDNONE Identifier (&INDNONE ',' &INDNONE Identifier )* + // implements &INDNONE ':' &INDNONE VarLiteral (&INDNONE ',' &INDNONE Identifier )* public static boolean ImplementsDirective(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "ImplementsDirective")) return false; if (!nextTokenIs(b, IMPLEMENTS)) return false; @@ -1997,7 +1997,7 @@ public static boolean ImplementsDirective(PsiBuilder b, int l) { r = r && report_error_(b, ImplementsDirective_1(b, l + 1)); r = p && report_error_(b, consumeToken(b, COLON)) && r; r = p && report_error_(b, ImplementsDirective_3(b, l + 1)) && r; - r = p && report_error_(b, consumeToken(b, IDENTIFIER)) && r; + r = p && report_error_(b, VarLiteral(b, l + 1)) && r; r = p && ImplementsDirective_5(b, l + 1) && r; exit_section_(b, l, m, r, p, null); return r || p; @@ -2070,14 +2070,14 @@ private static boolean ImplementsDirective_5_0_2(PsiBuilder b, int l) { /* ********************************************************** */ // ( import &INDNONE IMPORT_PATH &INDNONE as &INDNONE Identifier ) // | ( from &INDNONE IMPORT_PATH &INDNONE import &INDNONE Identifier ) - static boolean ImportDirective(PsiBuilder b, int l) { + public static boolean ImportDirective(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "ImportDirective")) return false; - if (!nextTokenIs(b, "", FROM, IMPORT)) return false; + if (!nextTokenIs(b, "", FROM, IMPORT)) return false; boolean r; - Marker m = enter_section_(b); + Marker m = enter_section_(b, l, _NONE_, IMPORT_DIRECTIVE, ""); r = ImportDirective_0(b, l + 1); if (!r) r = ImportDirective_1(b, l + 1); - exit_section_(b, m, null, r); + exit_section_(b, l, m, r, false, null); return r; } @@ -3682,13 +3682,13 @@ private static boolean CallExpression_0_3_0_0(PsiBuilder b, int l) { return r; } - // Identifier (&INDNONE'(') '{' StructExpressionMember (',' StructExpressionMember)* '}' ')' + // VarLiteral (&INDNONE'(') '{' StructExpressionMember (',' StructExpressionMember)* '}' ')' public static boolean StructExpression(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "StructExpression")) return false; if (!nextTokenIsSmart(b, IDENTIFIER)) return false; boolean r; Marker m = enter_section_(b); - r = consumeTokenSmart(b, IDENTIFIER); + r = VarLiteral(b, l + 1); r = r && StructExpression_1(b, l + 1); r = r && consumeToken(b, LBRACE); r = r && StructExpressionMember(b, l + 1); @@ -4074,7 +4074,7 @@ public static boolean PrimaryExpression(PsiBuilder b, int l) { return r; } - // log &INDNONE Identifier '(' Expression (',' Expression)* ')' + // log &INDNONE VarLiteral '(' Expression (',' Expression)* ')' public static boolean EventLogExpression(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "EventLogExpression")) return false; if (!nextTokenIsSmart(b, LOG)) return false; @@ -4082,7 +4082,8 @@ public static boolean EventLogExpression(PsiBuilder b, int l) { Marker m = enter_section_(b); r = consumeTokenSmart(b, LOG); r = r && EventLogExpression_1(b, l + 1); - r = r && consumeTokensSmart(b, 0, IDENTIFIER, LPAREN); + r = r && VarLiteral(b, l + 1); + r = r && consumeToken(b, LPAREN); r = r && Expression(b, l + 1, -1); r = r && EventLogExpression_5(b, l + 1); r = r && consumeToken(b, RPAREN); diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperEventDeclaration.java b/src/main/gen/org/vyperlang/plugin/psi/VyperEventDeclaration.java index 7438cbf..5ce715c 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperEventDeclaration.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperEventDeclaration.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface VyperEventDeclaration extends VyperElement { +public interface VyperEventDeclaration extends VyperNamedElement { @Nullable VyperEventProperty getEventProperty(); diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperEventLogExpression.java b/src/main/gen/org/vyperlang/plugin/psi/VyperEventLogExpression.java index 5b13fc0..d3bfbd9 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperEventLogExpression.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperEventLogExpression.java @@ -11,6 +11,6 @@ public interface VyperEventLogExpression extends VyperExpression { List getExpressionList(); @NotNull - PsiElement getIdentifier(); + VyperVarLiteral getVarLiteral(); } diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperImplementsDirective.java b/src/main/gen/org/vyperlang/plugin/psi/VyperImplementsDirective.java index a52ab66..d06b3a1 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperImplementsDirective.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperImplementsDirective.java @@ -7,4 +7,7 @@ public interface VyperImplementsDirective extends VyperElement { + @Nullable + VyperVarLiteral getVarLiteral(); + } diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperImportDirective.java b/src/main/gen/org/vyperlang/plugin/psi/VyperImportDirective.java new file mode 100644 index 0000000..2262152 --- /dev/null +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperImportDirective.java @@ -0,0 +1,16 @@ +// This is a generated file. Not intended for manual editing. +package org.vyperlang.plugin.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface VyperImportDirective extends VyperNamedElement { + + @Nullable + VyperImportPath getImportPath(); + + @Nullable + PsiElement getIdentifier(); + +} diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperStructExpression.java b/src/main/gen/org/vyperlang/plugin/psi/VyperStructExpression.java index 369f74d..6623b1e 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperStructExpression.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperStructExpression.java @@ -11,6 +11,6 @@ public interface VyperStructExpression extends VyperExpression { List getStructExpressionMemberList(); @NotNull - PsiElement getIdentifier(); + VyperVarLiteral getVarLiteral(); } diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperTypes.java b/src/main/gen/org/vyperlang/plugin/psi/VyperTypes.java index 99410ae..700ca5a 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperTypes.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperTypes.java @@ -39,6 +39,7 @@ public interface VyperTypes { IElementType IF_STATEMENT = new VyperElementType("IF_STATEMENT"); IElementType IMMUTABLE_DEFINITION_EXPRESSION = new VyperElementType("IMMUTABLE_DEFINITION_EXPRESSION"); IElementType IMPLEMENTS_DIRECTIVE = new VyperElementType("IMPLEMENTS_DIRECTIVE"); + IElementType IMPORT_DIRECTIVE = new VyperElementType("IMPORT_DIRECTIVE"); IElementType IMPORT_PATH = new VyperElementType("IMPORT_PATH"); IElementType INDEXED_DATA = new VyperElementType("INDEXED_DATA"); IElementType INDEX_ACCESS_EXPRESSION = new VyperElementType("INDEX_ACCESS_EXPRESSION"); @@ -263,6 +264,9 @@ else if (type == IMMUTABLE_DEFINITION_EXPRESSION) { else if (type == IMPLEMENTS_DIRECTIVE) { return new VyperImplementsDirectiveImpl(node); } + else if (type == IMPORT_DIRECTIVE) { + return new VyperImportDirectiveImpl(node); + } else if (type == IMPORT_PATH) { return new VyperImportPathImpl(node); } diff --git a/src/main/gen/org/vyperlang/plugin/psi/VyperVisitor.java b/src/main/gen/org/vyperlang/plugin/psi/VyperVisitor.java index 06927fb..a053e64 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/VyperVisitor.java +++ b/src/main/gen/org/vyperlang/plugin/psi/VyperVisitor.java @@ -49,7 +49,7 @@ public void visitEqExpression(@NotNull VyperEqExpression o) { } public void visitEventDeclaration(@NotNull VyperEventDeclaration o) { - visitElement(o); + visitNamedElement(o); } public void visitEventLogExpression(@NotNull VyperEventLogExpression o) { @@ -137,6 +137,10 @@ public void visitImplementsDirective(@NotNull VyperImplementsDirective o) { visitElement(o); } + public void visitImportDirective(@NotNull VyperImportDirective o) { + visitNamedElement(o); + } + public void visitInExpression(@NotNull VyperInExpression o) { visitExpression(o); } diff --git a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventDeclarationImpl.java b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventDeclarationImpl.java index 7f33ef8..c8b15eb 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventDeclarationImpl.java +++ b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventDeclarationImpl.java @@ -8,10 +8,10 @@ import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import static org.vyperlang.plugin.psi.VyperTypes.*; -import com.intellij.extapi.psi.ASTWrapperPsiElement; +import org.vyperlang.plugin.psi.VyperNamedElementImpl; import org.vyperlang.plugin.psi.*; -public class VyperEventDeclarationImpl extends ASTWrapperPsiElement implements VyperEventDeclaration { +public class VyperEventDeclarationImpl extends VyperNamedElementImpl implements VyperEventDeclaration { public VyperEventDeclarationImpl(@NotNull ASTNode node) { super(node); diff --git a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventLogExpressionImpl.java b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventLogExpressionImpl.java index ba0e973..1af4544 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventLogExpressionImpl.java +++ b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperEventLogExpressionImpl.java @@ -35,8 +35,8 @@ public List getExpressionList() { @Override @NotNull - public PsiElement getIdentifier() { - return findNotNullChildByType(IDENTIFIER); + public VyperVarLiteral getVarLiteral() { + return findNotNullChildByClass(VyperVarLiteral.class); } } diff --git a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImplementsDirectiveImpl.java b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImplementsDirectiveImpl.java index 33b6b2d..08d9880 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImplementsDirectiveImpl.java +++ b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImplementsDirectiveImpl.java @@ -27,4 +27,10 @@ public void accept(@NotNull PsiElementVisitor visitor) { else super.accept(visitor); } + @Override + @Nullable + public VyperVarLiteral getVarLiteral() { + return findChildByClass(VyperVarLiteral.class); + } + } diff --git a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImportDirectiveImpl.java b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImportDirectiveImpl.java new file mode 100644 index 0000000..f5fc1b8 --- /dev/null +++ b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperImportDirectiveImpl.java @@ -0,0 +1,42 @@ +// This is a generated file. Not intended for manual editing. +package org.vyperlang.plugin.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static org.vyperlang.plugin.psi.VyperTypes.*; +import org.vyperlang.plugin.psi.VyperImportImpl; +import org.vyperlang.plugin.psi.*; + +public class VyperImportDirectiveImpl extends VyperImportImpl implements VyperImportDirective { + + public VyperImportDirectiveImpl(@NotNull ASTNode node) { + super(node); + } + + public void accept(@NotNull VyperVisitor visitor) { + visitor.visitImportDirective(this); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof VyperVisitor) accept((VyperVisitor)visitor); + else super.accept(visitor); + } + + @Override + @Nullable + public VyperImportPath getImportPath() { + return findChildByClass(VyperImportPath.class); + } + + @Override + @Nullable + public PsiElement getIdentifier() { + return findChildByType(IDENTIFIER); + } + +} diff --git a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperStructExpressionImpl.java b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperStructExpressionImpl.java index 95a7fda..fcd8f94 100644 --- a/src/main/gen/org/vyperlang/plugin/psi/impl/VyperStructExpressionImpl.java +++ b/src/main/gen/org/vyperlang/plugin/psi/impl/VyperStructExpressionImpl.java @@ -35,8 +35,8 @@ public List getStructExpressionMemberList() { @Override @NotNull - public PsiElement getIdentifier() { - return findNotNullChildByType(IDENTIFIER); + public VyperVarLiteral getVarLiteral() { + return findNotNullChildByClass(VyperVarLiteral.class); } } diff --git a/src/main/kotlin/org/vyperlang/plugin/VyperLanguage.kt b/src/main/kotlin/org/vyperlang/plugin/VyperLanguage.kt index 9e7e3ee..10f3c34 100644 --- a/src/main/kotlin/org/vyperlang/plugin/VyperLanguage.kt +++ b/src/main/kotlin/org/vyperlang/plugin/VyperLanguage.kt @@ -3,8 +3,5 @@ package org.vyperlang.plugin import com.intellij.lang.Language object VyperLanguage : Language("Vyper", "text/vyper") { - override fun isCaseSensitive() = true } - - diff --git a/src/main/kotlin/org/vyperlang/plugin/VyperParserDefinition.kt b/src/main/kotlin/org/vyperlang/plugin/VyperParserDefinition.kt index 90d6278..f045bbe 100644 --- a/src/main/kotlin/org/vyperlang/plugin/VyperParserDefinition.kt +++ b/src/main/kotlin/org/vyperlang/plugin/VyperParserDefinition.kt @@ -1,6 +1,5 @@ package org.vyperlang.plugin - import com.intellij.lang.ASTNode import com.intellij.lang.ParserDefinition import com.intellij.lang.PsiParser diff --git a/src/main/kotlin/org/vyperlang/plugin/VyperStubGenerator.kt b/src/main/kotlin/org/vyperlang/plugin/VyperStubGenerator.kt index cde81af..d71b58a 100644 --- a/src/main/kotlin/org/vyperlang/plugin/VyperStubGenerator.kt +++ b/src/main/kotlin/org/vyperlang/plugin/VyperStubGenerator.kt @@ -13,7 +13,6 @@ import com.intellij.openapi.vfs.VirtualFileManager import org.vyperlang.plugin.settings.VyperSettings import java.io.File - object VyperStubGenerator { fun createStubInGenSourceFolder( @@ -51,7 +50,6 @@ object VyperStubGenerator { ModuleRootManager.getInstance(module).sourceRoots .firstOrNull { it.name == VyperSettings.INSTANCE.genarateOutputPath } - private fun generateFolder(module: Module, project: Project) { WriteCommandAction.runWriteCommandAction(project) { diff --git a/src/main/kotlin/org/vyperlang/plugin/actions/CompileVyperFileAction.kt b/src/main/kotlin/org/vyperlang/plugin/actions/CompileVyperFileAction.kt index dd95cc3..c335ded 100644 --- a/src/main/kotlin/org/vyperlang/plugin/actions/CompileVyperFileAction.kt +++ b/src/main/kotlin/org/vyperlang/plugin/actions/CompileVyperFileAction.kt @@ -15,7 +15,6 @@ import org.vyperlang.plugin.compile.VyperParameters import org.vyperlang.plugin.gui.NoFilesWithVyperAreSelectedDialogue import org.vyperlang.plugin.settings.VyperSettings - private const val COMPILING_MESSAGE = "Compiling Vyper" private val EXTENSION = VyperFileType.INSTANCE.defaultExtension diff --git a/src/main/kotlin/org/vyperlang/plugin/actions/CreateVyperFileAction.kt b/src/main/kotlin/org/vyperlang/plugin/actions/CreateVyperFileAction.kt index b5ad32c..94ab544 100644 --- a/src/main/kotlin/org/vyperlang/plugin/actions/CreateVyperFileAction.kt +++ b/src/main/kotlin/org/vyperlang/plugin/actions/CreateVyperFileAction.kt @@ -1,6 +1,5 @@ package org.vyperlang.plugin.actions - import com.intellij.ide.actions.CreateFileFromTemplateAction import com.intellij.ide.actions.CreateFileFromTemplateDialog import com.intellij.openapi.project.Project diff --git a/src/main/kotlin/org/vyperlang/plugin/annotators/ColorAnnotator.kt b/src/main/kotlin/org/vyperlang/plugin/annotators/ColorAnnotator.kt index 96c9f38..1812fbf 100644 --- a/src/main/kotlin/org/vyperlang/plugin/annotators/ColorAnnotator.kt +++ b/src/main/kotlin/org/vyperlang/plugin/annotators/ColorAnnotator.kt @@ -8,7 +8,6 @@ import org.vyperlang.plugin.VyperFileType import org.vyperlang.plugin.VyperInterfaceFileType import org.vyperlang.plugin.psi.* - /** * Annotator that highlights Vyper elements with different colors */ diff --git a/src/main/kotlin/org/vyperlang/plugin/annotators/VyperDeclarationsOrderAnnotator.kt b/src/main/kotlin/org/vyperlang/plugin/annotators/VyperDeclarationsOrderAnnotator.kt index 1472be5..73bf018 100644 --- a/src/main/kotlin/org/vyperlang/plugin/annotators/VyperDeclarationsOrderAnnotator.kt +++ b/src/main/kotlin/org/vyperlang/plugin/annotators/VyperDeclarationsOrderAnnotator.kt @@ -17,7 +17,7 @@ class VyperDeclarationsOrderAnnotator : Annotator { override fun annotate(element: PsiElement, holder: AnnotationHolder) { if (element is VyperStateVariableDeclaration) { - val declarations = (element.file as VyperFile).statements.takeWhile { it != element } + val declarations = (element.file as VyperFile).elements.takeWhile { it != element } loop@ for (dec in declarations) { when (dec) { diff --git a/src/main/kotlin/org/vyperlang/plugin/compile/VyperCompiler.kt b/src/main/kotlin/org/vyperlang/plugin/compile/VyperCompiler.kt index 0323ce4..974b6af 100644 --- a/src/main/kotlin/org/vyperlang/plugin/compile/VyperCompiler.kt +++ b/src/main/kotlin/org/vyperlang/plugin/compile/VyperCompiler.kt @@ -15,7 +15,6 @@ import org.vyperlang.plugin.docker.ToolResult import org.vyperlang.plugin.docker.VyperCompilerDocker import org.vyperlang.plugin.toolWindow.VyperWindow - data class VyperParameters( val module: Module, val project: Project, diff --git a/src/main/kotlin/org/vyperlang/plugin/completion/Completer.kt b/src/main/kotlin/org/vyperlang/plugin/completion/Completer.kt index b7936a5..cc57e37 100644 --- a/src/main/kotlin/org/vyperlang/plugin/completion/Completer.kt +++ b/src/main/kotlin/org/vyperlang/plugin/completion/Completer.kt @@ -15,37 +15,26 @@ import org.vyperlang.plugin.psi.* import org.vyperlang.plugin.psi.VyperTypes.* import org.vyperlang.plugin.references.VyperResolver import org.vyperlang.plugin.references.VyperResolver.resolveMemberAccess -import org.vyperlang.plugin.references.VyperResolver.resolveSelfVariables -import javax.swing.Icon object VyperCompleter { fun completeVarLiteral(element: VyperVarLiteral): Array = VyperResolver.lexicalDeclarations(element) - .map { createVarLookup(it) } + .map { createLookup(it) } .map { PrioritizedLookupElement.withPriority(it, 15.0) } .toTypedArray() - fun completeMemberAccess(element: VyperMemberAccessExpression): Array { - if (element.firstChild.firstChild is VyperVarLiteral - && (element.firstChild.firstChild as VyperVarLiteral).name == "self" - ) { - - val funDefs = (element.file as VyperFile).statements - .filterIsInstance() - .createFunDecLookups(VyperIcons.FILE) - - val stateVariables = resolveSelfVariables(element) - .map { it as VyperStateVariableDeclaration } - .createStateVarLookups(VyperIcons.FILE).toMutableList() - stateVariables.addAll(funDefs) - return stateVariables.toTypedArray() - } - return resolveMemberAccess(element).map { it as VyperLocalVariableDefinition } - .createLocalVarLookups(VyperIcons.FILE) - } + fun completeMemberAccess(element: VyperMemberAccessExpression): Array = + resolveMemberAccess(element) + .map { PrioritizedLookupElement.withPriority(this.createLookup(it), 15.0) } + .toTypedArray() - private fun createVarLookup(elem: VyperNamedElement): LookupElement = when (elem) { + /** + * Creates a lookup element for the given element. + * @param elem The named element to target. + * @return The lookup element. + */ + private fun createLookup(elem: VyperNamedElement): LookupElement = when (elem) { is VyperConstantDefinitionExpression -> LookupElementBuilder.create(elem, elem.name ?: "") .withIcon(VyperIcons.FILE) @@ -66,31 +55,17 @@ object VyperCompleter { .withIcon(VyperIcons.FILE) .withTypeText(elem.type.text ?: "") - else -> LookupElementBuilder.create(elem) - } - - - private fun Collection.createLocalVarLookups(icon: Icon): Array = - map { - LookupElementBuilder.create(it, it.name ?: "") - .withIcon(icon).withTypeText(it.type.text) - }.map { - PrioritizedLookupElement.withPriority(it, 15.0) - }.toTypedArray() + is VyperStateVariableDeclaration -> LookupElementBuilder + .create(elem, elem.name ?: "") + .withIcon(VyperIcons.FILE) + .withTypeText(elem.stateVariableType.text) - private fun Collection.createStateVarLookups(icon: Icon): Array = - map { - LookupElementBuilder.create(it, it.name ?: "") - .withIcon(icon).withTypeText(it.stateVariableType.text) - }.map { PrioritizedLookupElement.withPriority(it, 15.0) } - .toTypedArray() + is VyperFunctionDefinition -> LookupElementBuilder.create(elem, elem.name + "()") + .withIcon(VyperIcons.FILE) + .withTypeText("->${elem.funTypeAnnotation?.text ?: "()"}") - private fun Collection.createFunDecLookups(icon: Icon): Array = map { - LookupElementBuilder.create(it, it.name + "()") - .withIcon(icon).withTypeText("->${it.funTypeAnnotation?.text ?: "()"}") - }.map { - PrioritizedLookupElement.withPriority(it, 15.0) - }.toTypedArray() + else -> LookupElementBuilder.create(elem) + } } class VyperBaseTypesCompletionContributor : LookupContributor( @@ -183,4 +158,3 @@ abstract class LookupContributor(place: ElementPattern, vararg l }) } } - diff --git a/src/main/kotlin/org/vyperlang/plugin/docker/VyperCompilerDocker.kt b/src/main/kotlin/org/vyperlang/plugin/docker/VyperCompilerDocker.kt index 6ba9a27..3923569 100644 --- a/src/main/kotlin/org/vyperlang/plugin/docker/VyperCompilerDocker.kt +++ b/src/main/kotlin/org/vyperlang/plugin/docker/VyperCompilerDocker.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.vfs.VirtualFile import org.vyperlang.plugin.VyperMessageProcessor import javax.swing.event.HyperlinkEvent - /** * status code of execution */ diff --git a/src/main/kotlin/org/vyperlang/plugin/formating/VyperFormattingBlock.kt b/src/main/kotlin/org/vyperlang/plugin/formating/VyperFormattingBlock.kt index dc13598..eb21a23 100644 --- a/src/main/kotlin/org/vyperlang/plugin/formating/VyperFormattingBlock.kt +++ b/src/main/kotlin/org/vyperlang/plugin/formating/VyperFormattingBlock.kt @@ -108,7 +108,5 @@ class VyperFormattingBlock( override fun isIncomplete(): Boolean = isNodeIncomplete - override fun isLeaf(): Boolean = astNode.firstChildNode == null - -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/vyperlang/plugin/grammar/Vyper.bnf b/src/main/kotlin/org/vyperlang/plugin/grammar/Vyper.bnf index 8505056..0d5ad67 100644 --- a/src/main/kotlin/org/vyperlang/plugin/grammar/Vyper.bnf +++ b/src/main/kotlin/org/vyperlang/plugin/grammar/Vyper.bnf @@ -151,15 +151,17 @@ ImmutableDefinitionExpression ::= Identifier &INDNONE ':' ImmutableType { implements = "org.vyperlang.plugin.psi.VyperNamedElement" } -private ImportDirective ::= ( import &INDNONE IMPORT_PATH &INDNONE as &INDNONE Identifier ) +ImportDirective ::= ( import &INDNONE IMPORT_PATH &INDNONE as &INDNONE Identifier ) | ( from &INDNONE IMPORT_PATH &INDNONE import &INDNONE Identifier ) { pin(".*")=1 + mixin = "org.vyperlang.plugin.psi.VyperImportImpl" + implements = "org.vyperlang.plugin.psi.VyperNamedElement" } IMPORT_PATH ::= Identifier (&INDNONE '.' &INDNONE Identifier)* // implements statements -ImplementsDirective ::= implements &INDNONE ':' &INDNONE Identifier (&INDNONE ',' &INDNONE Identifier )* {pin=1} +ImplementsDirective ::= implements &INDNONE ':' &INDNONE VarLiteral (&INDNONE ',' &INDNONE Identifier )* {pin=1} // external interfaces ok ExternalInterfaces ::= interface &INDNONE Identifier &INDNONE ':' @@ -196,6 +198,8 @@ private structRecover ::= !(&INDEQ | &INDLT |<>) //Events must all come before global declarations and function definitions EventDeclaration ::= event &INDNONE Identifier &INDNONE ':' ((&INDGT EventProperty?) | (&INDNONE PassStatement)) { pin=5 + mixin = "org.vyperlang.plugin.psi.VyperNamedElementImpl" + implements = "org.vyperlang.plugin.psi.VyperNamedElement" } EventProperty ::= Identifier ':' (IndexedData | TYPE) (Identifier ':' (IndexedData |TYPE))* @@ -238,7 +242,6 @@ FunctionDefinition ::= FunctionModifier (&INDEQ FunctionModifier)* FunDef Functi mixin = "org.vyperlang.plugin.psi.VyperFunctionDefMixin" } - private FunctionVisibility ::= external | internal | deploy private FunctionMutability ::= pure | view | nonpayable | payable FunctionDecorator ::= FunctionVisibility | FunctionMutability | (nonreentrant ((&INDNONE '(') FunctionEntrancyKey ')')?) @@ -260,7 +263,6 @@ Statement ::= PassStatement private recoverStatement ::= !(&INDEQ|&INDLT) - private CondStmt ::= Expression &INDNONE ':' ((&INDNONE Statement) | <>) @@ -285,7 +287,6 @@ ForStatement ::= for &INDNONE Identifier &INDNONE in &INDNONE Expression &INDNON pin=1 } - private Continue ::= continue private Break ::= break @@ -328,7 +329,7 @@ Expression ::= | EventLogExpression | InExpression -EventLogExpression ::= log &INDNONE Identifier '(' Expression (',' Expression)* ')' +EventLogExpression ::= log &INDNONE VarLiteral '(' Expression (',' Expression)* ')' InExpression ::= Expression &INDNONE 'in' &INDNONE Expression @@ -342,7 +343,7 @@ RangeExpression ::= range &INDNONE '(' RangeInterval (',' 'bound' '=' Identifier StructExpressionMember ::= VarLiteral &INDNONE ':' &INDNONE Expression -StructExpression ::= Identifier (&INDNONE'(') '{' StructExpressionMember (',' StructExpressionMember)* '}' ')' +StructExpression ::= VarLiteral (&INDNONE'(') '{' StructExpressionMember (',' StructExpressionMember)* '}' ')' AssignmentExpression ::= Expression (&INDNONE ('=' | '+=' | '-=' | '*=' | '/=' | '%=')) @@ -366,7 +367,6 @@ FunctionCallExpression ::= (Identifier &INDNONE FunctionCallArguments) | //implements and mixin } - //left recursion? MemberAccessExpression ::= Expression &INDNONE '.' (&INDNONE VarLiteral) { name = "member access" @@ -379,7 +379,6 @@ ParenthesiziedExpression ::= '(' Expression ')' {pin = 1} ClearExpression ::= clear &INDNONE '(' Expression ')' {pin=1} - UnaryExpression ::= (NOT | '~' | '+' | '-') &INDNONE Expression InlineArrayExpression ::= '[' Expression (',' Expression)* ']' {pin = 1} AndExpression ::= Expression AND Expression @@ -411,7 +410,6 @@ VarLiteral ::= Identifier {implements = "org.vyperlang.plugin.psi.VyperReference //BuiltIn ::= 'bitwise_and' | 'bitwise_not' | 'bitwise_or' | 'bitwise_xor' | 'shift' | 'create_minimal_proxy_to' | 'create_copy_of' | 'create_from_blueprint' | 'raw_call' | 'raw_log' | 'raw_revert' | 'selfdestruct' | 'send' | 'ecadd' | 'ecmul' | 'ecrecover' | 'keccak256' | 'sha256' | 'concat' | 'convert' | 'uint2str' | 'extract32' | 'slice' | 'abs' | 'ceil' | 'epsilon' | 'floor' | 'max' | 'max_value' | 'min' | 'min_value' | 'pow_mod256' | 'sqrt' | 'isqrt' | 'uint256_addmod' | 'uint256_mulmod' | 'unsafe_add' | 'unsafe_sub' | 'unsafe_mul' | 'unsafe_div' | 'as_wei_value' | 'blockhash' | 'empty' | 'len' | 'method_id' | '_abi_encode' | '_abi_decode' | 'print' - // TYPES seems okay TYPE ::= ListType | MapType | ValueType | StructType diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisStatusResponse.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisStatusResponse.kt deleted file mode 100644 index c16ae3a..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisStatusResponse.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - -import com.google.gson.annotations.SerializedName - -data class AnalysisStatusResponse( - @SerializedName("harveyVersion") - val harveyVersion: String = "", - @SerializedName("submittedBy") - val submittedBy: String = "", - @SerializedName("apiVersion") - val apiVersion: String = "", - @SerializedName("mythrilVersion") - val mythrilVersion: String = "", - @SerializedName("maruVersion") - val maruVersion: String = "", - @SerializedName("runTime") - val runTime: Int = 0, - @SerializedName("error") - val error: String = "", - @SerializedName("submittedAt") - val submittedAt: String = "", - @SerializedName("uuid") - val uuid: String = "", - @SerializedName("maestroVersion") - val maestroVersion: String = "", - @SerializedName("queueTime") - val queueTime: Int = 0, - @SerializedName("status") - val status: String = "" -) \ No newline at end of file diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisSubmitResponse.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisSubmitResponse.kt deleted file mode 100644 index e042d4f..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/AnalysisSubmitResponse.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - - -data class AnalysisSubmitResponse( - val harveyVersion: String, - val submittedBy: String, - val apiVersion: String, - val mythrilVersion: String, - val maruVersion: String, - val submittedAt: String, - val uuid: String, - val maestroVersion: String, - val queueTime: Int, - val status: String -) \ No newline at end of file diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ApiMythX.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ApiMythX.kt deleted file mode 100644 index 8274c7a..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ApiMythX.kt +++ /dev/null @@ -1,107 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - -import com.github.kittinunf.fuel.Fuel -import com.github.kittinunf.fuel.core.FuelError -import com.github.kittinunf.fuel.core.Headers -import com.github.kittinunf.fuel.core.Response -import com.github.kittinunf.fuel.core.extensions.jsonBody -import com.github.kittinunf.fuel.coroutines.awaitStringResponseResult -import com.github.kittinunf.result.Result -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken - -import java.lang.reflect.Type - -class APIMythX { - private val cite = "https://api.mythx.io/v1/" - private val loginEndPoint = "${cite}auth/login" - private val refreshTokenEndPoint = "${cite}auth/refresh" - private val analyzeEndPoint = "${cite}analyses" - private val gson = Gson() - - val waitTimeOfAnalysis = 15000L // in seconds - val retryCounts = 5// minutes at most - - - private fun whenHandler( - response: Response, - result: Result, - typeToken: Type - ): Pair { - return when (response.statusCode) { - 200 -> { - Pair(gson.fromJson(result.component1()!!, typeToken), null) - } - 401 -> { - return try { - Pair( - null, gson.fromJson(response.body().asString("application/json"), ErrorResponse::class.java) - ) - } catch (err: Error) { - Pair(null, ErrorResponse(response.body().asString("application/json"), 401)) - } - } - else -> { - Pair(null, gson.fromJson(response.body().asString("application/json"), ErrorResponse::class.java)) - } - } - } - - suspend fun login(ethAddress: String, password: String): Pair { - val (_, response, result) = - Fuel.post(loginEndPoint) - .jsonBody("{ \"ethAddress\" : \"$ethAddress\", \"password\" : \"$password\" }") - .awaitStringResponseResult() - return whenHandler(response, result, object : TypeToken() {}.type) - } - - - suspend fun refreshAuthToken(tokens: JwtTokens): Pair { - val (_, response, result) = - Fuel.post(refreshTokenEndPoint) - .jsonBody( - "{ \"jwtTokens\" : { \"access\" : \"${tokens.access}\", \"refresh\" : \"${tokens.refresh}\" } }" - ) - .awaitStringResponseResult() - return whenHandler(response, result, object : TypeToken() {}.type) - } - - suspend fun getAnalysisStatus(uuid: String, tokens: JwtTokens): Pair { - val (_, response, result) = - Fuel.get("$analyzeEndPoint/$uuid") - .header(Headers.AUTHORIZATION, "Bearer ${tokens.access}") - .awaitStringResponseResult() - - return whenHandler(response, result, object : TypeToken() {}.type) - } - - suspend fun getDetectedIssue(uuid: String, tokens: JwtTokens): Pair?, ErrorResponse?> { - val (_, response, result) = - Fuel.get("$analyzeEndPoint/$uuid/issues") - .header(Headers.AUTHORIZATION, "Bearer ${tokens.access}") - .awaitStringResponseResult() - - return whenHandler(response, result, object : TypeToken>() {}.type) - } - - suspend fun partialAnalyze(tokens: JwtTokens, bytecode: String, deployedBytecode: String): - Pair { - val (_, response, result) = - Fuel.post(analyzeEndPoint) - .header(Headers.AUTHORIZATION, "Bearer ${tokens.access}") - .jsonBody( - """ - { - "clientToolName":"vyper-intelij-plugin", - "data": { - "bytecode": "$bytecode", - "deployedBytecode" : "$deployedBytecode" - } - } - - """.trimIndent() - ) - .awaitStringResponseResult() - return whenHandler(response, result, object : TypeToken() {}.type) - } -} \ No newline at end of file diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ErrorResponse.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ErrorResponse.kt deleted file mode 100644 index 5594342..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ErrorResponse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - -import com.google.gson.annotations.SerializedName - -data class ErrorResponse( - @SerializedName("error") - val error: String = "", - @SerializedName("status") - val status: Int = 0 -) - - diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ReponseLogin.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ReponseLogin.kt deleted file mode 100644 index f8f6066..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/ReponseLogin.kt +++ /dev/null @@ -1,41 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - - -import com.google.gson.annotations.SerializedName - -//""" -//"jwtTokens": -//{ -// -// "access": "string", -// "refresh": "string" -// -//}, -//"access": "string", -//"refresh": "string" -//""" - - -data class LoginReponse( - @SerializedName("access") - val access: String = "", - @SerializedName("refresh") - val refresh: String = "", - @SerializedName("jwtTokens") - val jwtTokens: JwtTokens -) - - -data class RefreshResponse( - @SerializedName("jwtTokens") - val jwtTokens: JwtTokens -) - -data class JwtTokens( - @SerializedName("access") - val access: String = "", - @SerializedName("refresh") - val refresh: String = "" -) - - diff --git a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/detectedIssuesResponse.kt b/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/detectedIssuesResponse.kt deleted file mode 100644 index ac869ea..0000000 --- a/src/main/kotlin/org/vyperlang/plugin/internalApi/mythx/detectedIssuesResponse.kt +++ /dev/null @@ -1,55 +0,0 @@ -package org.vyperlang.plugin.internalApi.mythx - -import com.google.gson.annotations.SerializedName - - -data class Description( - @SerializedName("head") - val head: String = "", - @SerializedName("tail") - val tail: String = "" -) - - -data class DetectedIssue( - @SerializedName("sourceList") - val sourceList: List?, - @SerializedName("sourceType") - val sourceType: String = "", - @SerializedName("meta") - val meta: Any, - @SerializedName("issues") - val issues: List?, - @SerializedName("sourceFormat") - val sourceFormat: String = "" -) - - -data class IssuesItem( - @SerializedName("severity") - val severity: String = "", - @SerializedName("swcTitle") - val swcTitle: String = "", - @SerializedName("swcID") - val swcID: String = "", - @SerializedName("extra") - val extra: Any, - @SerializedName("description") - val description: Description, - @SerializedName("locations") - val locations: List? -) - - -data class LocationsItem( - @SerializedName("sourceList") - val sourceList: List?, - @SerializedName("sourceMap") - val sourceMap: String = "", - @SerializedName("sourceType") - val sourceType: String = "", - @SerializedName("sourceFormat") - val sourceFormat: String = "" -) - - diff --git a/src/main/kotlin/org/vyperlang/plugin/parser/ParserUtil.kt b/src/main/kotlin/org/vyperlang/plugin/parser/ParserUtil.kt index 8a18c6e..3c172ba 100644 --- a/src/main/kotlin/org/vyperlang/plugin/parser/ParserUtil.kt +++ b/src/main/kotlin/org/vyperlang/plugin/parser/ParserUtil.kt @@ -7,9 +7,6 @@ import com.intellij.openapi.util.Key import com.intellij.psi.TokenType import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet -import org.vyperlang.plugin.parser.ParserUtil.Companion.parserStateKey -import org.vyperlang.plugin.parser.ParserUtil.ParserState - class ParserUtil : GeneratedParserUtilBase() { diff --git a/src/main/kotlin/org/vyperlang/plugin/psi/Factory.kt b/src/main/kotlin/org/vyperlang/plugin/psi/Factory.kt index adf4055..1979e5f 100644 --- a/src/main/kotlin/org/vyperlang/plugin/psi/Factory.kt +++ b/src/main/kotlin/org/vyperlang/plugin/psi/Factory.kt @@ -4,13 +4,9 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiFileFactory import org.vyperlang.plugin.VyperFileType - class VyperPsiFactory(val project: Project) { - - - fun createStruct(struct: String): VyperStructDefinition { - return createFromText(struct) ?: error("Failed to create struct: `$struct`") - } + fun createStruct(struct: String): VyperStructDefinition = + createFromText(struct) ?: error("Failed to create struct: `$struct`") private inline fun createFromText(code: String): T? = PsiFileFactory.getInstance(project) diff --git a/src/main/kotlin/org/vyperlang/plugin/psi/Impl.kt b/src/main/kotlin/org/vyperlang/plugin/psi/Impl.kt index bcbf603..36cf38f 100644 --- a/src/main/kotlin/org/vyperlang/plugin/psi/Impl.kt +++ b/src/main/kotlin/org/vyperlang/plugin/psi/Impl.kt @@ -24,3 +24,7 @@ abstract class VyperNamedElementImpl(node: ASTNode) : VyperElementImpl(node), Vy override fun getTextOffset(): Int = nameIdentifier?.textOffset ?: super.getTextOffset() } + +abstract class VyperImportImpl(node: ASTNode) : VyperNamedElementImpl(node) { + override fun getNameIdentifier(): PsiElement? = findLastChildByType(IDENTIFIER) +} diff --git a/src/main/kotlin/org/vyperlang/plugin/psi/Mixins.kt b/src/main/kotlin/org/vyperlang/plugin/psi/Mixins.kt index 9dca830..18d9f95 100644 --- a/src/main/kotlin/org/vyperlang/plugin/psi/Mixins.kt +++ b/src/main/kotlin/org/vyperlang/plugin/psi/Mixins.kt @@ -1,47 +1,25 @@ package org.vyperlang.plugin.psi - import com.intellij.lang.ASTNode import com.intellij.openapi.util.IconLoader import com.intellij.psi.PsiElement -import com.intellij.psi.util.childrenOfType -import com.intellij.psi.util.parentOfType import org.vyperlang.plugin.psi.VyperTypes.* -import org.vyperlang.plugin.psi.impl.VyperCallExpressionImpl import org.vyperlang.plugin.references.* abstract class VyperVarLiteralMixin(node: ASTNode) : VyperNamedElementImpl(node), VyperVarLiteral { override val referenceNameElement: PsiElement get() = findChildByType(IDENTIFIER)!! override val referenceName: String get() = referenceNameElement.text - override fun getReference(): VyperReference { - val parent = node.psi.parent - val grandparent = parent.parent - return when { - parent is VyperStructExpressionMember && parent.firstChild == node.psi -> { - val structExpression = parent.parentOfType() - val structMember = - node.psi.file.childrenOfType() - .firstOrNull { it.name == structExpression?.identifier?.text } - ?.childrenOfType() - ?.firstOrNull { it.identifier.text == this.text } - VyperStructMemberReference(this, structMember) - } - grandparent is VyperCallExpressionImpl && parent is VyperMemberAccessExpression -> - VyperMemberAccessReference(this, parent) - parent is VyperMemberAccessExpression && parent.varLiteral == node.psi -> - VyperMemberAccessReference(this, parent) - else -> VyperVarLiteralReference(this) - } -// if (parent is VyperCallElement) return VyperCallReference(parent) -// if (grandparent is VyperCallElement) return VyperCallReference(grandparent) -//member access -// if (parent is VyperSelfAccessExpression) return VyperSelfAccessReference(this,parent) -// if (parent is VyperMemberAccessExpression && parent.varLiteral == node.psi) return VyperMemberAccessReference(this,parent) + override fun getReference(): VyperReference = when (node.psi.parent) { + is VyperImplementsDirective -> VyperStructReference(this) + is VyperEventLogExpression -> VyperEventLogReference(this) + is VyperStructExpression -> VyperStructReference(this) + is VyperStructExpressionMember -> VyperStructMemberReference(this) + is VyperMemberAccessExpression -> VyperMemberAccessReference(this, node.psi.parent as VyperMemberAccessExpression) + else -> VyperVarLiteralReference(this) } } - abstract class VyperCallElement(node: ASTNode) : VyperNamedElementImpl(node), VyperCallExpression { /** * Finds the name of the function being called. diff --git a/src/main/kotlin/org/vyperlang/plugin/psi/VyperFile.kt b/src/main/kotlin/org/vyperlang/plugin/psi/VyperFile.kt index 0a102c7..25bb197 100644 --- a/src/main/kotlin/org/vyperlang/plugin/psi/VyperFile.kt +++ b/src/main/kotlin/org/vyperlang/plugin/psi/VyperFile.kt @@ -12,5 +12,11 @@ class VyperFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, Vype override fun toString(): String = fileType.name - val statements: List get() = PsiTreeUtil.getChildrenOfAnyType(this, VyperElement::class.java) + val elements: List get() = PsiTreeUtil.getChildrenOfAnyType(this, VyperElement::class.java) + + val selfElements: MutableList get() = PsiTreeUtil.getChildrenOfAnyType(this, VyperFunctionDefinition::class.java, VyperStateVariableDeclaration::class.java) + + val functions: List get() = PsiTreeUtil.getChildrenOfAnyType(this, VyperFunctionDefinition::class.java) + + val stateVariables: List get () = PsiTreeUtil.getChildrenOfAnyType(this, VyperStateVariableDeclaration::class.java) } diff --git a/src/main/kotlin/org/vyperlang/plugin/references/Resolver.kt b/src/main/kotlin/org/vyperlang/plugin/references/Resolver.kt index a99ad11..d17c62e 100644 --- a/src/main/kotlin/org/vyperlang/plugin/references/Resolver.kt +++ b/src/main/kotlin/org/vyperlang/plugin/references/Resolver.kt @@ -1,17 +1,58 @@ package org.vyperlang.plugin.references import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.util.childrenOfType import com.intellij.psi.util.isAncestor +import com.intellij.psi.util.parentOfType import org.vyperlang.plugin.psi.* import org.vyperlang.plugin.psi.VyperTypes.VAR_LITERAL - object VyperResolver { + /** + * Resolves a variable literal to its declaration. + */ fun resolveVarLiteral(element: VyperNamedElement): List = lexicalDeclarations(element).filter { it.name == element.name }.toList() + /** + * Finds all the lexical declarations applicable to the given place. + * @param place The element that is being resolved. + * @param stop A function that stops the search when it returns true. Default is to search the whole file. + */ fun lexicalDeclarations(place: PsiElement, stop: (PsiElement) -> Boolean = { false }): List = - lexicalDeclRec(place, stop).distinct() + place.ancestors + .drop(1) // current element might not be a VyperElement + .takeWhile { (it is VyperElement || it is VyperFile) && !stop(it) } + .flatMap { lexicalDeclarations(it, place) } + .filter { !it.isAncestor(place) } // don't suggest the element being defined + .distinct() + .toList() + + /** + * Resolves a struct to its declaration. + * @param element The variable literal that is referencing a struct. + */ + fun resolveStruct(element: VyperVarLiteral): PsiElement? = findStruct(element.file, element.name) + + /** + * Resolves a struct member to its declaration. + * @param element The variable literal that is a member of a struct. + */ + fun resolveStructMember(element: VyperVarLiteral): PsiElement? = + // find the definition of the struct + findStruct(element.file, element.parentOfType()?.varLiteral?.identifier?.text) + // then find the member in it + ?.childrenOfType() + ?.firstOrNull { it.identifier.text == element.text } + + private fun findStruct(file: PsiFile, structName: String?) = + file.childrenOfType() + .firstOrNull { it.name == structName } + + fun resolveEventLog(element: VyperVarLiteral): Collection = + element.file.childrenOfType() + .filter { it.identifier.text == element.text } // private fun getImportDecls(element: PsiElement): List { // val newList = element.file.children.filterIsInstance().map { it -> @@ -24,18 +65,13 @@ object VyperResolver { // return newList // } - private fun lexicalDeclRec(place: PsiElement, stop: (PsiElement) -> Boolean): List = - place.ancestors - .drop(1) // current element might not be a VyperElement - .takeWhile { (it is VyperElement || it is VyperFile) && !stop(it) } - .flatMap { lexicalDeclarations(it, place) } - .filter { !it.isAncestor(place) } // don't suggest the element being defined - .toList() - private fun lexicalDeclarations(scope: PsiElement, place: PsiElement): List = when (scope) { is VyperLocalVariableDefinition -> listOf(scope) + is VyperImportDirective -> listOf(scope) + is VyperStructDefinition -> listOf(scope) is VyperConstantDefinitionExpression -> listOf(scope) is VyperImmutableDefinitionExpression -> listOf(scope) + is VyperStatement -> scope.prevSiblings .filterIsInstance() .map { it.childOfType() } @@ -43,36 +79,29 @@ object VyperResolver { .flatMap { lexicalDeclarations(it, place) } .toList() - is VyperFile -> scope.statements - .filter { it !is VyperFunctionDefinition } + is VyperFile -> scope.elements + .filter { it !is VyperFunctionDefinition } // don't suggest functions as that will suggest parameters .flatMap { lexicalDeclarations(it, place) } is VyperFunctionDefinition -> scope.parameters?.paramDefList ?: emptyList() else -> emptyList() } - fun resolveFunction(element: VyperCallExpression): Collection = when { - element.firstChild is VyperPrimaryExpression -> emptyList() - element.firstChild is VyperMemberAccessExpression && - (element.firstChild.firstChild.firstChild as VyperVarLiteral).name == "self" -> - (element.file as VyperFile) - .statements - .filterIsInstance() - .filter { it.name == element.referenceName } - .map { FunctionResolveResult(it) } + // todo: this needs to be rewritten. Checking first child is wrong. We need to iterate in all the children + // all expressions and arguments: CallExpression = Expression ('[' Expression ']')* FunctionCallArguments FunctionCallArguments* + fun resolveCall(element: VyperCallExpression): Collection = when (element.firstChild) { + is VyperMemberAccessExpression -> resolveMemberAccess(element.firstChild as VyperMemberAccessExpression) else -> emptyList() } fun resolveMemberAccess(element: VyperMemberAccessExpression): List = when { - element.firstChild.firstChild is VyperVarLiteral - && (element.firstChild.firstChild as VyperVarLiteral).name == "msg" - -> + element.getFirstLiteral().name == "msg" -> VyperInternalTypeFactory(element.project).msg.children.filterIsInstance() element.firstChild.firstChild is VyperVarLiteral && (element.firstChild.firstChild as VyperVarLiteral).name == "self" - -> resolveSelfVariableLiteral( + -> getSelfLiteral( element, findLastChildByType(VAR_LITERAL, element.node)!!.psi as VyperVarLiteral ) @@ -80,21 +109,11 @@ object VyperResolver { else -> emptyList() } - //now only for self.var - //typechecking to be implemented - private fun resolveSelfVariableLiteral( - element: VyperMemberAccessExpression, - id: VyperVarLiteral - ): List = - resolveSelfVariables(element) - .plus(resolveSelfAccessFunction(element)) + fun getSelfLiteral(element: VyperMemberAccessExpression, id: VyperVarLiteral) = + getSelfElements(element) .filter { it.name == id.name } - private fun resolveSelfAccessFunction(element: VyperMemberAccessExpression): List = - (element.file as VyperFile).statements.filterIsInstance() - - fun resolveSelfVariables(element: VyperMemberAccessExpression): List = - (element.file as VyperFile).statements.filterIsInstance() + fun getSelfElements(element: VyperMemberAccessExpression) = (element.file as VyperFile).selfElements } -data class FunctionResolveResult(val psiElement: PsiElement, val usingLibrary: Boolean = false) \ No newline at end of file +fun VyperMemberAccessExpression.getFirstLiteral() = this.firstChild.firstChild as VyperVarLiteral diff --git a/src/main/kotlin/org/vyperlang/plugin/references/VyperReferenceBase.kt b/src/main/kotlin/org/vyperlang/plugin/references/VyperReferenceBase.kt index 148e6b2..964325f 100644 --- a/src/main/kotlin/org/vyperlang/plugin/references/VyperReferenceBase.kt +++ b/src/main/kotlin/org/vyperlang/plugin/references/VyperReferenceBase.kt @@ -35,7 +35,6 @@ abstract class VyperReferenceBase(element: T) override fun resolve(): VyperElement? = super.resolve() as VyperElement? - // protected open fun doRename(identifier: PsiElement, newName: String) { // check(identifier.elementType == IDENTIFIER) // identifier.replace(SolPsiFactory(identifier.project).createIdentifier(newName.replace(".sol", ""))) diff --git a/src/main/kotlin/org/vyperlang/plugin/references/VyperUserDefinedReferences.kt b/src/main/kotlin/org/vyperlang/plugin/references/VyperUserDefinedReferences.kt index 0554811..04346a0 100644 --- a/src/main/kotlin/org/vyperlang/plugin/references/VyperUserDefinedReferences.kt +++ b/src/main/kotlin/org/vyperlang/plugin/references/VyperUserDefinedReferences.kt @@ -3,7 +3,6 @@ package org.vyperlang.plugin.references import com.intellij.psi.PsiElement import org.vyperlang.plugin.completion.VyperCompleter import org.vyperlang.plugin.psi.VyperCallElement -import org.vyperlang.plugin.psi.VyperLocalVariableDefinition import org.vyperlang.plugin.psi.VyperMemberAccessExpression import org.vyperlang.plugin.psi.VyperVarLiteral @@ -24,13 +23,19 @@ class VyperMemberAccessReference(element: VyperVarLiteral, var member: VyperMemb } class VyperCallReference(element: VyperCallElement) : VyperReferenceBase(element), VyperReference { - private fun resolveFunctionCall(): Collection = VyperResolver.resolveFunction(element) + private fun resolveFunctionCall() = VyperResolver.resolveCall(element) - override fun multiResolve(): Collection = resolveFunctionCall().map { it.psiElement } + override fun multiResolve() = resolveFunctionCall() } -class VyperStructMemberReference(element: VyperVarLiteral, private val structMember: VyperLocalVariableDefinition?) : - VyperReferenceBase(element), VyperReference { +class VyperStructReference(element: VyperVarLiteral) : VyperReferenceBase(element), VyperReference { + override fun singleResolve(): PsiElement? = VyperResolver.resolveStruct(element) +} + +class VyperStructMemberReference(element: VyperVarLiteral) : VyperReferenceBase(element), VyperReference { + override fun singleResolve(): PsiElement? = VyperResolver.resolveStructMember(element) +} - override fun singleResolve(): PsiElement? = structMember +class VyperEventLogReference(element: VyperVarLiteral) : VyperReferenceBase(element), VyperReference { + override fun multiResolve(): Collection = VyperResolver.resolveEventLog(element) } diff --git a/src/main/kotlin/org/vyperlang/plugin/settings/VyperConfigurablePanel.kt b/src/main/kotlin/org/vyperlang/plugin/settings/VyperConfigurablePanel.kt index bbcd3a9..d2f36e7 100644 --- a/src/main/kotlin/org/vyperlang/plugin/settings/VyperConfigurablePanel.kt +++ b/src/main/kotlin/org/vyperlang/plugin/settings/VyperConfigurablePanel.kt @@ -20,13 +20,10 @@ class VyperConfigurablePanel { //private lateinit var password: JPasswordField private lateinit var password: JTextField - // createStubInGenSourceFolder stubs internal lateinit var generateStubsPanel: JPanel private lateinit var generateStubs: JCheckBox private lateinit var genOutputPath: JTextField - // - internal lateinit var compilerPanel: JPanel @@ -73,7 +70,6 @@ class VyperConfigurablePanel { .settingsConfigChanged() } - fun reset(settings: VyperSettings) { usesCustomAccount.isSelected = settings.usesCustomAccount generateStubs.isSelected = settings.generateStubs @@ -105,7 +101,6 @@ class VyperConfigurablePanel { } } - fun isModified(settings: VyperSettings): Boolean = usesCustomAccount.isSelected != settings.usesCustomAccount || diff --git a/src/main/kotlin/org/vyperlang/plugin/settings/settings.kt b/src/main/kotlin/org/vyperlang/plugin/settings/settings.kt index 99151a8..dc05380 100644 --- a/src/main/kotlin/org/vyperlang/plugin/settings/settings.kt +++ b/src/main/kotlin/org/vyperlang/plugin/settings/settings.kt @@ -46,7 +46,6 @@ class VyperSettings : PersistentStateComponent { } } - class VyperSettingsConfigurable : Configurable { private var component: VyperConfigurablePanel? = null private val name: String = "Vyper" @@ -81,7 +80,6 @@ class VyperSettingsConfigurable : Configurable { component = null } - // fun getQuickFix(project: Project): Runnable = // Runnable { ShowSettingsUtil.getInstance().editConfigurable(project, this) } } diff --git a/src/main/kotlin/org/vyperlang/plugin/toolWindow/VyperWindow.kt b/src/main/kotlin/org/vyperlang/plugin/toolWindow/VyperWindow.kt index 68beaf7..4ccb681 100644 --- a/src/main/kotlin/org/vyperlang/plugin/toolWindow/VyperWindow.kt +++ b/src/main/kotlin/org/vyperlang/plugin/toolWindow/VyperWindow.kt @@ -46,7 +46,6 @@ object VyperWindow { getToolWindow(project).show() } - /** * Creates tab with scrollable panel with JTextPane for specified @param toolWindow */ @@ -63,7 +62,6 @@ object VyperWindow { toolWindow.contentManager.addContent(content) } - /** * Return concrete component where output would be written * If not exists then it would be created diff --git a/src/test/kotlin/org/vyperlang/plugin/parser/TestFindUsages.kt b/src/test/kotlin/org/vyperlang/plugin/parser/TestFindUsages.kt index aa89460..37896d6 100644 --- a/src/test/kotlin/org/vyperlang/plugin/parser/TestFindUsages.kt +++ b/src/test/kotlin/org/vyperlang/plugin/parser/TestFindUsages.kt @@ -7,7 +7,6 @@ import com.intellij.util.Processor import org.vyperlang.plugin.VyperFileType import org.vyperlang.plugin.usages.VyperFindUsagesProvider - class TestFindUsages : BasePlatformTestCase() { fun testConstant() { val code = """ @@ -65,7 +64,7 @@ class TestFindUsages : BasePlatformTestCase() { def foo() -> Foo: return Foo({ab: 1}) """ - checkUsages(code) + checkUsages(code, 67 to 70) } fun testStructMember() { @@ -88,7 +87,7 @@ class TestFindUsages : BasePlatformTestCase() { def foo() -> uint256: log Log(1) """ - checkUsages(code) + checkUsages(code, 69 to 72) } fun testImport(){ @@ -99,7 +98,7 @@ class TestFindUsages : BasePlatformTestCase() { def balanceOf(a: address) -> uint256: return ERC20(a).balanceOf(self) """ - checkUsages(code) + checkUsages(code, 10 to 20) } private fun checkUsages(code: String, vararg expectedRanges: Pair) {