diff --git a/src/main/java/com/reason/ide/IconProvider.java b/src/main/java/com/reason/ide/IconProvider.java index 1a37ba0f5..6c55d1f15 100644 --- a/src/main/java/com/reason/ide/IconProvider.java +++ b/src/main/java/com/reason/ide/IconProvider.java @@ -41,6 +41,8 @@ public Icon getIcon(@NotNull PsiElement element, int flags) { return ORIcons.EXCEPTION; } else if (element instanceof RPsiInnerModule innerModule) { return innerModule.isModuleType() ? ORIcons.INNER_MODULE_INTF : ORIcons.INNER_MODULE; + } else if (element instanceof RPsiModuleSignature) { + return ORIcons.MODULE_TYPE; } else if (element instanceof RPsiFunctor) { return ORIcons.FUNCTOR; } else if (element instanceof RPsiType) { diff --git a/src/main/java/com/reason/ide/go/ORLineMarkerProvider.java b/src/main/java/com/reason/ide/go/ORLineMarkerProvider.java index ae433e5cd..39e4cde15 100644 --- a/src/main/java/com/reason/ide/go/ORLineMarkerProvider.java +++ b/src/main/java/com/reason/ide/go/ORLineMarkerProvider.java @@ -52,12 +52,12 @@ private void collectLetNavigationMarkers(@NotNull RPsiLet element, @NotNull Proj boolean inInterface = module != null && module.isInterfaceFile(); if (module instanceof RPsiInnerModule innerModule) { - inInterface = innerModule.isModuleType(); + inInterface = innerModule.isModuleType() || inInterface; String letName = element.getName(); if (letName != null) { targets = inInterface - ? findTargetFromInterfaceModule((RPsiInnerModule) module, letName, RPsiVar.class, scope) - : findTargetFromImplementationModule((RPsiInnerModule) module, letName, RPsiVar.class); + ? findTargetFromInterfaceModule(innerModule, letName, RPsiVar.class, scope) + : findTargetFromImplementationModule(innerModule, letName, RPsiVar.class); } } else if (module != null) { // Top module navigation @@ -68,7 +68,7 @@ private void collectLetNavigationMarkers(@NotNull RPsiLet element, @NotNull Proj } else { resolvedElements = qName == null ? null : LetFqnIndex.getElements(qName, project, scope); } - targets = resolveTargetFromIndex(module.isInterfaceFile(), resolvedElements); + targets = resolveTargetFromIndex(inInterface, resolvedElements); } RelatedItemLineMarkerInfo marker = createMarkerInfo(element, inInterface, "let/val", targets); @@ -78,17 +78,20 @@ private void collectLetNavigationMarkers(@NotNull RPsiLet element, @NotNull Proj } private void collectValNavigationMarkers(@NotNull RPsiVal element, @NotNull Project project, @NotNull GlobalSearchScope scope, @NotNull Collection> result) { + List targets = null; + RPsiModule module = PsiTreeUtil.getStubOrPsiParentOfType(element, RPsiModule.class); boolean inInterface = module != null && module.isInterfaceFile(); - List targets = null; - if (module instanceof RPsiInnerModule) { - String elementName = element.getName(); - if (elementName != null) { - targets = inInterface ? findTargetFromInterfaceModule((RPsiInnerModule) module, elementName, RPsiVar.class, scope) - : findTargetFromImplementationModule((RPsiInnerModule) module, elementName, RPsiVar.class); + if (module instanceof RPsiInnerModule innerModule) { + inInterface = innerModule.isModuleType() || inInterface; + String valName = element.getName(); + if (valName != null) { + targets = inInterface + ? findTargetFromInterfaceModule(innerModule, valName, RPsiVar.class, scope) + : findTargetFromImplementationModule(innerModule, valName, RPsiVar.class); } - } else { + } else if (module != null) { // Top module navigation String qName = element.getQualifiedName(); Collection resolvedElements = qName == null ? null : LetFqnIndex.getElements(qName, project, scope); diff --git a/src/main/java/com/reason/ide/structure/StructureViewElement.java b/src/main/java/com/reason/ide/structure/StructureViewElement.java index cab3bf160..9ad2ec750 100644 --- a/src/main/java/com/reason/ide/structure/StructureViewElement.java +++ b/src/main/java/com/reason/ide/structure/StructureViewElement.java @@ -114,19 +114,23 @@ public Icon getIcon(boolean unused) { return new ItemPresentation() { @Override public @NotNull String getPresentableText() { + if (myElement instanceof PsiNamedElement namedElement) { + String name = namedElement.getName(); + if (name != null) { + return name; + } + } return "Unknown presentation for element " + myElement.getText(); } - @Nullable @Override - public String getLocationString() { - return null; + public @NotNull String getLocationString() { + return ""; } - @Nullable @Override - public Icon getIcon(boolean unused) { - return null; + public @Nullable Icon getIcon(boolean unused) { + return PsiIconUtil.getProvidersIcon(myElement, 0); } }; } @@ -171,19 +175,21 @@ else if (myElement instanceof RPsiDuneStanza) { private @NotNull List buildModuleStructure(@NotNull RPsiInnerModule moduleElement) { List treeElements = new ArrayList<>(); - RPsiModuleSignature moduleType = moduleElement.getModuleSignature(); - PsiElement rootElement = moduleType; - if (rootElement == null) { - rootElement = moduleElement.getBody(); + RPsiModuleSignature moduleSignature = moduleElement.getModuleSignature(); + if (moduleSignature != null) { + treeElements.add(new StructureViewElement(moduleSignature, myLevel + 1)); } - if (rootElement != null) { - rootElement.acceptChildren(new ElementVisitor(treeElements, myLevel)); + if (moduleSignature == null) { + PsiElement body = moduleElement.getBody(); + if (body != null) { + body.acceptChildren(new ElementVisitor(treeElements, myLevel)); + } } // Process body if there is a signature - if (moduleType != null) { - rootElement = moduleElement.getBody(); + if (moduleSignature != null) { + PsiElement rootElement = moduleElement.getBody(); if (rootElement != null) { treeElements.add(new StructureModuleImplView(rootElement)); } @@ -256,12 +262,12 @@ else if (myElement instanceof RPsiDuneStanza) { } static class ElementVisitor extends PsiElementVisitor { - private final List m_treeElements; - private final int m_elementLevel; + private final List myTreeElements; + private final int myElementLevel; ElementVisitor(List elements, int elementLevel) { - m_treeElements = elements; - m_elementLevel = elementLevel; + myTreeElements = elements; + myElementLevel = elementLevel; } @Override @@ -273,23 +279,23 @@ public void visitElement(@NotNull PsiElement element) { // it's a tuple! add each element of the tuple separately. for (PsiElement child : let.getScopeChildren()) { if (child instanceof RPsiLowerSymbol) { - m_treeElements.add(new StructureViewElement(child, element, true, m_elementLevel)); + myTreeElements.add(new StructureViewElement(child, element, true, myElementLevel)); } } return; } } - m_treeElements.add(new StructureViewElement(element, m_elementLevel)); + myTreeElements.add(new StructureViewElement(element, myElementLevel)); } } else if (element instanceof RPsiRecord) { for (RPsiRecordField field : ((RPsiRecord) element).getFields()) { - m_treeElements.add(new StructureViewElement(field, m_elementLevel)); + myTreeElements.add(new StructureViewElement(field, myElementLevel)); } - } else if (element instanceof RPsiScopedExpr && m_elementLevel < 2) { + } else if (element instanceof RPsiScopedExpr && myElementLevel < 2) { List children = ORUtil.findImmediateChildrenOfClass(element, RPsiStructuredElement.class); for (RPsiStructuredElement child : children) { if (child.canBeDisplayed()) { - m_treeElements.add(new StructureViewElement(child, m_elementLevel)); + myTreeElements.add(new StructureViewElement(child, myElementLevel)); } } } diff --git a/src/main/java/com/reason/lang/core/psi/impl/RPsiInnerModuleImpl.java b/src/main/java/com/reason/lang/core/psi/impl/RPsiInnerModuleImpl.java index 2a6602c5e..f4f49376f 100644 --- a/src/main/java/com/reason/lang/core/psi/impl/RPsiInnerModuleImpl.java +++ b/src/main/java/com/reason/lang/core/psi/impl/RPsiInnerModuleImpl.java @@ -184,6 +184,8 @@ public boolean isFunctorCall() { } public ItemPresentation getPresentation() { + //RPsiModuleSignature moduleSignature = getModuleSignature(); + return new ItemPresentation() { @Override public @Nullable String getPresentableText() { @@ -192,6 +194,7 @@ public ItemPresentation getPresentation() { @Override public @NotNull String getLocationString() { + //return moduleSignature != null ? moduleSignature.getQualifiedName() : getQualifiedName(); return getQualifiedName(); } @@ -206,6 +209,6 @@ public ItemPresentation getPresentation() { @Override public String toString() { - return "RPsiModule:" + getModuleName(); + return super.toString() + ":" + getModuleName(); } } diff --git a/src/main/java/com/reason/lang/ocaml/OclParser.java b/src/main/java/com/reason/lang/ocaml/OclParser.java index 8f62fb545..73d7be35a 100644 --- a/src/main/java/com/reason/lang/ocaml/OclParser.java +++ b/src/main/java/com/reason/lang/ocaml/OclParser.java @@ -1265,7 +1265,7 @@ private void parseExternal() { @SuppressWarnings("StatementWithEmptyBody") private void parseType() { - if (is(myTypes.C_MODULE_DECLARATION)) { + if (is(myTypes.C_MODULE_DECLARATION) || is(myTypes.C_MODULE_SIGNATURE)) { // module |>type<| M = ... } else if (is(myTypes.C_TYPE_VARIABLE)) { // let x : |>type<| ... @@ -1349,10 +1349,8 @@ private void parseLet() { private void parseModule() { if (is(myTypes.C_LET_DECLARATION)) { updateComposite(myTypes.C_MODULE_DECLARATION); - } else if (!is(myTypes.C_MACRO_NAME)) { - if (!is(myTypes.C_MODULE_SIGNATURE)) { - popEndUntilScope(); - } + } else if (!is(myTypes.C_MACRO_NAME) && !is(myTypes.C_MODULE_SIGNATURE)) { + popEndUntilScope(); mark(myTypes.C_MODULE_DECLARATION); } } diff --git a/src/test/java/com/reason/ide/structure/StructureOCLTest.java b/src/test/java/com/reason/ide/structure/StructureOCLTest.java index a23648fb1..fc13ac3c9 100644 --- a/src/test/java/com/reason/ide/structure/StructureOCLTest.java +++ b/src/test/java/com/reason/ide/structure/StructureOCLTest.java @@ -87,7 +87,7 @@ public void test_module_type_extraction() { TreeElement e = model.getRoot().getChildren()[0]; assertPresentation("X", "B.X", ORIcons.INNER_MODULE, e.getPresentation()); TreeElement ee = e.getChildren()[0]; - assertPresentation("A.S", "", ORIcons.MODULE_TYPE, ee.getPresentation()); + assertPresentation("S", "", ORIcons.MODULE_TYPE, ee.getPresentation()); } @Test @@ -99,7 +99,7 @@ public void test_module_type_extraction_functor() { TreeElement e = model.getRoot().getChildren()[0]; assertPresentation("X", "B.X", ORIcons.INNER_MODULE, e.getPresentation()); TreeElement ee = e.getChildren()[0]; - assertPresentation("A.Vcs.Branch", "", ORIcons.MODULE_TYPE, ee.getPresentation()); + assertPresentation("Branch", "", ORIcons.MODULE_TYPE, ee.getPresentation()); } // https://github.com/giraud/reasonml-idea-plugin/issues/274 @@ -140,7 +140,11 @@ public void test_GH_407() { // https://github.com/giraud/reasonml-idea-plugin/issues/408 @Test public void test_GH_408() { - FileBase e = configureCode("A.ml", "let a =\n let x = 0 in\n x"); + FileBase e = configureCode("A.ml", """ + let a = + let x = 0 in + x + """); StructureViewModel model = new ORStructureViewModel(e); TreeElement fn = model.getRoot().getChildren()[0]; diff --git a/src/test/java/com/reason/lang/ocaml/ModuleParsingTest.java b/src/test/java/com/reason/lang/ocaml/ModuleParsingTest.java index 25e7c3336..e1f4923cc 100644 --- a/src/test/java/com/reason/lang/ocaml/ModuleParsingTest.java +++ b/src/test/java/com/reason/lang/ocaml/ModuleParsingTest.java @@ -176,8 +176,11 @@ public void test_GH_91() { assertEquals(2, expressions(file).size()); assertEquals("Branch", first(moduleExpressions(file)).getName()); RPsiInnerModule e = (RPsiInnerModule) expressions(file).iterator().next(); + RPsiModuleSignature modType = e.getModuleSignature(); assertEquals("module type of Vcs_.Branch", modType.getText()); - assertNull(modType.getName()); + assertNull(PsiTreeUtil.findChildOfType(modType, RPsiInnerModule.class)); + assertEquals("Branch", modType.getName()); + //assertEquals("Vcs_.Branch", modType.getQualifiedName()); } }