Skip to content

Commit

Permalink
#310 - Missing types in structure panel after class definition
Browse files Browse the repository at this point in the history
  • Loading branch information
giraud committed Mar 19, 2021
1 parent a3edd85 commit db790bf
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 168 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ are solved.

## Unreleased

- :bug: [#310](https://github.com/reasonml-editor/reasonml-idea-plugin/issues/310) ![o] Missing types in structure panel after class definition

# 0.98.1 - 2021/03/02

- :bug: [#293](https://github.com/reasonml-editor/reasonml-idea-plugin/issues/293) ![o] Better 'and' parsing
Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ allprojects {
untilBuild = pluginUntilBuild
changeNotes """
<ul>
<li>#293 - Incorrectly parsing 'and' in pattern match</li>
<li>Better integration with yarn workspaces (v2?): search for node_modules in parent directory also</li>
<li>#310 - Missing types in structure panel after class definition</li>
</ul>
<p><a href="https://github.com/reasonml-editor/reasonml-idea-plugin/blob/master/CHANGELOG.md">Full change log...</a></p>
<p/>
Expand Down
4 changes: 4 additions & 0 deletions src/com/reason/lang/ocaml/OclParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,10 @@ private void parseEnd(@NotNull ParserState state) {
state.advance().mark(m_types.C_MODULE_DECLARATION).resolution(module).setStart();
}
}
else if (scope.isCompositeType(m_types.C_OBJECT)) {
// Close a class
state.popEnd();
}
}
}

Expand Down
213 changes: 117 additions & 96 deletions tests/com/reason/lang/ocaml/ClassParsingTest.java
Original file line number Diff line number Diff line change
@@ -1,104 +1,125 @@
package com.reason.lang.ocaml;

import com.intellij.psi.*;
import com.reason.ide.files.*;
import com.reason.lang.core.psi.PsiClass;
import com.reason.lang.core.psi.impl.PsiClassField;
import com.reason.lang.core.psi.impl.PsiClassMethod;
import com.reason.lang.core.psi.PsiType;
import com.reason.lang.core.psi.impl.*;

import java.util.*;

@SuppressWarnings("ConstantConditions")
public class ClassParsingTest extends OclParsingTestCase {
public void test_basic() {
Collection<PsiClass> classes = classExpressions(parseCode("class foo = object end"));

assertEquals(1, classes.size());
assertEquals("foo", first(classes).getName());
}

public void test_classType() {
Collection<PsiClass> classes =
classExpressions(
parseCode(
"class type restricted_point_type = object method get_x : int method bump : unit end"));

assertEquals(1, classes.size());
assertEquals("restricted_point_type", first(classes).getName());
}

public void test_fields() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object val mutable a = [] val b = 2 end"));

PsiClass clazz = first(classes);
Collection<PsiClassField> fields = clazz.getFields();
assertEquals(fields.size(), 2);
}

public void test_methods() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object method get_x = x method get_y = y end"));

PsiClass clazz = first(classes);
Collection<PsiClassMethod> methods = clazz.getMethods();
assertEquals(methods.size(), 2);
}

public void test_both() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object val mutable x = [] method get_x = x end"));

PsiClass clazz = first(classes);
assertEquals(clazz.getFields().size(), 1);
assertEquals(clazz.getMethods().size(), 1);
}

public void test_classConstraint() {
Collection<PsiClass> classes =
classExpressions(
parseCode(
"class ['a] circle (c : 'a) = object constraint 'a = #point val mutable center = c method set_center c = center <- c method move = center#move end"));

PsiClass clazz = first(classes);
assertEquals("circle", first(classes).getName());
assertNotNull(clazz.getParameters());
assertNotNull(clazz.getConstructor());
assertEquals(clazz.getFields().size(), 1);
assertEquals(clazz.getMethods().size(), 2);
}

public void test_GH_268() {
PsiClass clazz =
first(
classExpressions(
parseCode(
"class tag : text_tag -> object method as_tag : text_tag method connect : tag_signals end")));

assertSize(2, clazz.getMethods());
}

public void test_GH_269() {
PsiClass e =
first(
classExpressions(
parseCode(
"class type ops = object\n method go_to_insert : unit task\n method go_to_mark : GText.mark -> unit task\n method process_next_phrase : unit task\n method get_n_errors : int\n method get_errors : (int * string) list\n method get_slaves_status : int * int * string CString.Map.t\n method handle_failure : handle_exn_rty -> unit task\n method destroy : unit -> unit end")));

assertSize(8, e.getMethods());
ArrayList<PsiClassMethod> methods = new ArrayList<>(e.getMethods());
assertEquals("go_to_insert", methods.get(0).getName());
assertEquals("unit task", methods.get(0).getSignature().getText());
assertEquals("go_to_mark", methods.get(1).getName());
assertEquals("GText.mark -> unit task", methods.get(1).getSignature().getText());
assertEquals("process_next_phrase", methods.get(2).getName());
assertEquals("unit task", methods.get(2).getSignature().getText());
assertEquals("get_n_errors", methods.get(3).getName());
assertEquals("int", methods.get(3).getSignature().getText());
assertEquals("get_errors", methods.get(4).getName());
assertEquals("(int * string) list", methods.get(4).getSignature().getText());
assertEquals("get_slaves_status", methods.get(5).getName());
assertEquals("int * int * string CString.Map.t", methods.get(5).getSignature().getText());
assertEquals("handle_failure", methods.get(6).getName());
assertEquals("handle_exn_rty -> unit task", methods.get(6).getSignature().getText());
assertEquals("destroy", methods.get(7).getName());
assertEquals("unit -> unit", methods.get(7).getSignature().getText());
}
public void test_basic() {
Collection<PsiClass> classes = classExpressions(parseCode("class foo = object end"));

assertEquals(1, classes.size());
assertEquals("foo", first(classes).getName());
}

public void test_classType() {
Collection<PsiClass> classes =
classExpressions(
parseCode(
"class type restricted_point_type = object method get_x : int method bump : unit end"));

assertEquals(1, classes.size());
assertEquals("restricted_point_type", first(classes).getName());
}

public void test_fields() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object val mutable a = [] val b = 2 end"));

PsiClass clazz = first(classes);
Collection<PsiClassField> fields = clazz.getFields();
assertEquals(fields.size(), 2);
}

public void test_methods() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object method get_x = x method get_y = y end"));

PsiClass clazz = first(classes);
Collection<PsiClassMethod> methods = clazz.getMethods();
assertEquals(methods.size(), 2);
}

public void test_both() {
Collection<PsiClass> classes =
classExpressions(parseCode("class foo = object val mutable x = [] method get_x = x end"));

PsiClass clazz = first(classes);
assertEquals(clazz.getFields().size(), 1);
assertEquals(clazz.getMethods().size(), 1);
}

public void test_classConstraint() {
Collection<PsiClass> classes =
classExpressions(
parseCode(
"class ['a] circle (c : 'a) = object constraint 'a = #point val mutable center = c method set_center c = center <- c method move = center#move end"));

PsiClass clazz = first(classes);
assertEquals("circle", first(classes).getName());
assertNotNull(clazz.getParameters());
assertNotNull(clazz.getConstructor());
assertEquals(clazz.getFields().size(), 1);
assertEquals(clazz.getMethods().size(), 2);
}

public void test_GH_268() {
PsiClass clazz =
first(
classExpressions(
parseCode(
"class tag : text_tag -> object method as_tag : text_tag method connect : tag_signals end")));

assertSize(2, clazz.getMethods());
}

public void test_GH_269() {
PsiClass e =
first(
classExpressions(
parseCode(
"class type ops = object\n method go_to_insert : unit task\n method go_to_mark : GText.mark -> unit task\n method process_next_phrase : unit task\n method get_n_errors : int\n method get_errors : (int * string) list\n method get_slaves_status : int * int * string CString.Map.t\n method handle_failure : handle_exn_rty -> unit task\n method destroy : unit -> unit end")));

assertSize(8, e.getMethods());
ArrayList<PsiClassMethod> methods = new ArrayList<>(e.getMethods());
assertEquals("go_to_insert", methods.get(0).getName());
assertEquals("unit task", methods.get(0).getSignature().getText());
assertEquals("go_to_mark", methods.get(1).getName());
assertEquals("GText.mark -> unit task", methods.get(1).getSignature().getText());
assertEquals("process_next_phrase", methods.get(2).getName());
assertEquals("unit task", methods.get(2).getSignature().getText());
assertEquals("get_n_errors", methods.get(3).getName());
assertEquals("int", methods.get(3).getSignature().getText());
assertEquals("get_errors", methods.get(4).getName());
assertEquals("(int * string) list", methods.get(4).getSignature().getText());
assertEquals("get_slaves_status", methods.get(5).getName());
assertEquals("int * int * string CString.Map.t", methods.get(5).getSignature().getText());
assertEquals("handle_failure", methods.get(6).getName());
assertEquals("handle_exn_rty -> unit task", methods.get(6).getSignature().getText());
assertEquals("destroy", methods.get(7).getName());
assertEquals("unit -> unit", methods.get(7).getSignature().getText());
}

// https://github.com/reasonml-editor/reasonml-idea-plugin/issues/310
public void test_GH_310() {
FileBase file = parseCode("class type control =\n" +
" object\n" +
" method detach : unit -> unit\n" +
" end\n" +
"\n" +
"type errpage = (int * string) list page");
List<PsiNamedElement> es = (List<PsiNamedElement>) expressions(file);

assertSize(2, es);
assertInstanceOf(es.get(0), PsiClass.class);
assertEquals("control", es.get(0).getName());
assertInstanceOf(es.get(1), PsiType.class);
assertEquals("errpage", es.get(1).getName());
}

}
Loading

0 comments on commit db790bf

Please sign in to comment.