From 18cf4bf20eb990255b85594f97e5ab9077bd7a9d Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Tue, 8 Dec 2015 21:28:19 -0600 Subject: [PATCH 01/10] Highlight module attributes Use `CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES` to match color used for "ERL_ATTRIBUTE" in intellij-erlang. --- .idea/runConfigurations/org_elixir_lang.xml | 6 +- src/META-INF/plugin.xml | 1 + .../elixir_lang/ElixirColorSettingsPage.java | 1 + .../elixir_lang/ElixirSyntaxHighlighter.java | 8 ++ .../annonator/ModuleAttribute.java | 84 +++++++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/org/elixir_lang/annonator/ModuleAttribute.java diff --git a/.idea/runConfigurations/org_elixir_lang.xml b/.idea/runConfigurations/org_elixir_lang.xml index 5d666c1c5..b7efe1aa9 100644 --- a/.idea/runConfigurations/org_elixir_lang.xml +++ b/.idea/runConfigurations/org_elixir_lang.xml @@ -17,7 +17,7 @@ - + @@ -28,8 +28,6 @@ - - + \ No newline at end of file diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index e06a565e6..ce25cdb5e 100644 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -498,6 +498,7 @@ + diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index d90a2de80..a240d6ef7 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -35,6 +35,7 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Kernel Functions", ElixirSyntaxHighlighter.KERNEL_FUNCTION), new AttributesDescriptor("Kernel Macros", ElixirSyntaxHighlighter.KERNEL_MACRO), new AttributesDescriptor("Kernel.SpecialForms Macros", ElixirSyntaxHighlighter.KERNEL_SPECIAL_FORMS_MACRO), + new AttributesDescriptor("Module Attributes", ElixirSyntaxHighlighter.MODULE_ATTRIBUTE), new AttributesDescriptor("Non-Decimal Base Prefix", ElixirSyntaxHighlighter.WHOLE_NUMBER_BASE), new AttributesDescriptor("Obsolete Non-Decimal Base Prefix", ElixirSyntaxHighlighter.OBSOLETE_WHOLE_NUMBER_BASE), new AttributesDescriptor("Operation Sign", ElixirSyntaxHighlighter.OPERATION_SIGN), diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index ce55b1241..f0a752953 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -3,11 +3,13 @@ import com.intellij.lexer.Lexer; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.openapi.editor.HighlighterColors; +import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.xmlb.annotations.Text; import org.elixir_lang.psi.ElixirTypes; import org.jetbrains.annotations.NotNull; @@ -87,6 +89,12 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { DefaultLanguageHighlighterColors.KEYWORD ); + public static final TextAttributesKey MODULE_ATTRIBUTE = createTextAttributesKey( + "ELIXIR_MODULE_ATTRIBUTE", + // Color used for "ERL_ATTRIBUTE" in intellij-erlang + CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES + ); + public static final TextAttributesKey OBSOLETE_WHOLE_NUMBER_BASE = createTextAttributesKey( "ELIXIR_OBSOLETE_WHOLE_NUMBER_BASE", HighlighterColors.BAD_CHARACTER diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java new file mode 100644 index 000000000..f00734b5f --- /dev/null +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -0,0 +1,84 @@ +package org.elixir_lang.annonator; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiRecursiveElementVisitor; +import org.elixir_lang.ElixirSyntaxHighlighter; +import org.elixir_lang.psi.AtUnqualifiedNoParenthesesCall; +import org.elixir_lang.psi.ElixirUnmatchedAtUnqualifiedNoParenthesesCall; +import org.elixir_lang.psi.Quotable; +import org.elixir_lang.psi.impl.ElixirPsiImplUtil; +import org.jetbrains.annotations.NotNull; + +/** + * Annotates module attributes. + */ +public class ModuleAttribute implements Annotator, DumbAware { + /* + * Public Instance Methods + */ + + /** + * Annotates the specified PSI element. + * It is guaranteed to be executed in non-reentrant fashion. + * I.e there will be no call of this method for this instance before previous call get completed. + * Multiple instances of the annotator might exist simultaneously, though. + * + * @param element to annotate. + * @param holder the container which receives annotations created by the plugin. + */ + @Override + public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder holder) { + element.accept( + new PsiRecursiveElementVisitor() { + public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall) { + ASTNode node = atUnqualifiedNoParenthesesCall.getNode(); + ASTNode[] identifierNodes = node.getChildren(ElixirPsiImplUtil.IDENTIFIER_TOKEN_SET); + + assert identifierNodes.length == 1; + + Quotable atPrefixOperator = atUnqualifiedNoParenthesesCall.getAtPrefixOperator(); + ASTNode identifierNode = identifierNodes[0]; + + TextRange textRange = new TextRange( + atPrefixOperator.getTextRange().getStartOffset(), + identifierNode.getTextRange().getEndOffset() + ); + + highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + } + + @Override + public void visitElement(@NotNull final PsiElement element) { + if (element instanceof AtUnqualifiedNoParenthesesCall) { + visitAtUnqualifiedNoParenthesesCall((AtUnqualifiedNoParenthesesCall) element); + } + } + } + ); + } + + /* + * Private Instance Methods + */ + + /** + * Highlights `textRange` with the given `textAttributesKey`. + * + * @param textRange textRange in the document to highlight + * @param annotationHolder the container which receives annotations created by the plugin. + * @param textAttributesKey text attributes to apply to the `node`. + */ + private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHolder annotationHolder, @NotNull final TextAttributesKey textAttributesKey) { + annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(TextAttributes.ERASE_MARKER); + annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)); + } +} From 4369eb5d8d82d573c22933486d638ee3ba4c3163 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 10 Dec 2015 21:32:27 -0600 Subject: [PATCH 02/10] Highlight @doc, @moduledoc, and @typedoc "Documentation Module Attributes" inherits from DOC_COMMENT_TAG to match intellj-elixir using DOC_COMMENT_TAG for @doc. --- src/org/elixir_lang/ElixirColorSettingsPage.java | 1 + src/org/elixir_lang/ElixirSyntaxHighlighter.java | 5 +++++ src/org/elixir_lang/annonator/ModuleAttribute.java | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index a240d6ef7..66306e8b5 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -28,6 +28,7 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Character Token", ElixirSyntaxHighlighter.CHAR_TOKEN_TOKEN), new AttributesDescriptor("Comment", ElixirSyntaxHighlighter.COMMENT), new AttributesDescriptor("Decimal Exponent, Mark, and Separator", ElixirSyntaxHighlighter.DECIMAL), + new AttributesDescriptor("Documentation Module Attributes", ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE), new AttributesDescriptor("Escape Sequence", ElixirSyntaxHighlighter.VALID_ESCAPE_SEQUENCE), new AttributesDescriptor("Expression Substitution Mark", ElixirSyntaxHighlighter.EXPRESSION_SUBSTITUTION_MARK), new AttributesDescriptor("Identifier", ElixirSyntaxHighlighter.IDENTIFIER), diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index f0a752953..38cc675cd 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -54,6 +54,11 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { DefaultLanguageHighlighterColors.NUMBER ); + public static final TextAttributesKey DOCUMENTATION_MODULE_ATTRIBUTE = createTextAttributesKey( + "ELIXIR_DOCUMENTATION_MODULE_ATTRIBUTE", + DefaultLanguageHighlighterColors.DOC_COMMENT_TAG + ); + public static final TextAttributesKey EXPRESSION_SUBSTITUTION_MARK = createTextAttributesKey( "ELIXIR_EXPRESSION_SUBSTITUTION_MARK", DefaultLanguageHighlighterColors.PARENTHESES diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index f00734b5f..68d8bb90c 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -53,7 +53,16 @@ public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoPa identifierNode.getTextRange().getEndOffset() ); - highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + + String identifier = identifierNode.getText(); + + if (identifier.equals("doc") || + identifier.equals("moduledoc") || + identifier.equals("typedoc")) { + highlight(textRange, holder, ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE); + } else { + highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + } } @Override From 6d0a6713c70ff89f4f030cf2a67aa559ad519c53 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 10 Dec 2015 22:57:39 -0600 Subject: [PATCH 03/10] Ignore user dictionaries in project files --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f1d5d0ea..7f28d25b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /tmp -/.idea/shelf # user-specific project metadata +/.idea/dictionaries/ /.idea/workspace.xml /.idea/shelf/ # ignore idea.xml output From 7d26c62b4733b00de6a7ed2c9956f7efb3e7d798 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 10 Dec 2015 22:59:30 -0600 Subject: [PATCH 04/10] Highlight argument to @doc, @moduledoc, and @typedoc arguments The heredoc or line after `@doc`, `@moduledoc`, or `@typedoc` will be highlighted as Documentation Text, which defaults to DOC_COMMENT_TAG_VALUE. --- .../elixir_lang/psi/ElixirCharListLine.java | 5 +- gen/org/elixir_lang/psi/ElixirStringLine.java | 4 +- gen/org/elixir_lang/psi/ElixirVisitor.java | 2 + .../psi/impl/ElixirCharListLineImpl.java | 6 ++ .../psi/impl/ElixirStringLineImpl.java | 5 ++ src/org/elixir_lang/Elixir.bnf | 8 +- .../elixir_lang/ElixirColorSettingsPage.java | 1 + .../elixir_lang/ElixirSyntaxHighlighter.java | 5 ++ .../annonator/ModuleAttribute.java | 79 ++++++++++++++++++- src/org/elixir_lang/psi/Line.java | 2 +- src/org/elixir_lang/psi/SigilLine.java | 2 +- .../psi/impl/ElixirPsiImplUtil.java | 23 ++++-- 12 files changed, 126 insertions(+), 16 deletions(-) diff --git a/gen/org/elixir_lang/psi/ElixirCharListLine.java b/gen/org/elixir_lang/psi/ElixirCharListLine.java index e4e84e93d..1f0d78c96 100644 --- a/gen/org/elixir_lang/psi/ElixirCharListLine.java +++ b/gen/org/elixir_lang/psi/ElixirCharListLine.java @@ -9,7 +9,7 @@ import java.util.List; -public interface ElixirCharListLine extends Atomable, InterpolatedCharList, Quotable { +public interface ElixirCharListLine extends Atomable, InterpolatedCharList, Line, Quotable { @NotNull ElixirQuoteCharListBody getQuoteCharListBody(); @@ -23,6 +23,9 @@ public interface ElixirCharListLine extends Atomable, InterpolatedCharList, Quot @NotNull List addHexadecimalEscapeSequenceCodePoints(List codePointList, ASTNode child); + @NotNull + Body getBody(); + IElementType getFragmentType(); @NotNull diff --git a/gen/org/elixir_lang/psi/ElixirStringLine.java b/gen/org/elixir_lang/psi/ElixirStringLine.java index eb3d4dca9..9628a00a2 100644 --- a/gen/org/elixir_lang/psi/ElixirStringLine.java +++ b/gen/org/elixir_lang/psi/ElixirStringLine.java @@ -9,7 +9,7 @@ import java.util.List; -public interface ElixirStringLine extends Atomable, InterpolatedString, Quotable { +public interface ElixirStringLine extends Atomable, InterpolatedString, Line, Quotable { @NotNull ElixirQuoteStringBody getQuoteStringBody(); @@ -23,6 +23,8 @@ public interface ElixirStringLine extends Atomable, InterpolatedString, Quotable @NotNull List addHexadecimalEscapeSequenceCodePoints(List codePointList, ASTNode child); + Body getBody(); + IElementType getFragmentType(); @NotNull diff --git a/gen/org/elixir_lang/psi/ElixirVisitor.java b/gen/org/elixir_lang/psi/ElixirVisitor.java index 5d05a2683..15c0e484b 100644 --- a/gen/org/elixir_lang/psi/ElixirVisitor.java +++ b/gen/org/elixir_lang/psi/ElixirVisitor.java @@ -111,6 +111,7 @@ public void visitCharListHeredocLine(@NotNull ElixirCharListHeredocLine o) { public void visitCharListLine(@NotNull ElixirCharListLine o) { visitAtomable(o); // visitInterpolatedCharList(o); + // visitLine(o); // visitQuotable(o); } @@ -748,6 +749,7 @@ public void visitStringHeredocLine(@NotNull ElixirStringHeredocLine o) { public void visitStringLine(@NotNull ElixirStringLine o) { visitAtomable(o); // visitInterpolatedString(o); + // visitLine(o); // visitQuotable(o); } diff --git a/gen/org/elixir_lang/psi/impl/ElixirCharListLineImpl.java b/gen/org/elixir_lang/psi/impl/ElixirCharListLineImpl.java index 9992a0ca4..035032063 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirCharListLineImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirCharListLineImpl.java @@ -7,6 +7,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.tree.IElementType; +import org.elixir_lang.psi.Body; import org.elixir_lang.psi.ElixirCharListLine; import org.elixir_lang.psi.ElixirQuoteCharListBody; import org.elixir_lang.psi.ElixirVisitor; @@ -46,6 +47,11 @@ public List addHexadecimalEscapeSequenceCodePoints(List codePo return ElixirPsiImplUtil.addHexadecimalEscapeSequenceCodePoints(this, codePointList, child); } + @NotNull + public Body getBody() { + return ElixirPsiImplUtil.getBody(this); + } + public IElementType getFragmentType() { return ElixirPsiImplUtil.getFragmentType(this); } diff --git a/gen/org/elixir_lang/psi/impl/ElixirStringLineImpl.java b/gen/org/elixir_lang/psi/impl/ElixirStringLineImpl.java index 2061fcbd7..625db8ca6 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirStringLineImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirStringLineImpl.java @@ -7,6 +7,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.tree.IElementType; +import org.elixir_lang.psi.Body; import org.elixir_lang.psi.ElixirQuoteStringBody; import org.elixir_lang.psi.ElixirStringLine; import org.elixir_lang.psi.ElixirVisitor; @@ -46,6 +47,10 @@ public List addHexadecimalEscapeSequenceCodePoints(List codePo return ElixirPsiImplUtil.addHexadecimalEscapeSequenceCodePoints(this, codePointList, child); } + public Body getBody() { + return ElixirPsiImplUtil.getBody(this); + } + public IElementType getFragmentType() { return ElixirPsiImplUtil.getFragmentType(this); } diff --git a/src/org/elixir_lang/Elixir.bnf b/src/org/elixir_lang/Elixir.bnf index 24461e092..dd1fa25b9 100644 --- a/src/org/elixir_lang/Elixir.bnf +++ b/src/org/elixir_lang/Elixir.bnf @@ -685,7 +685,7 @@ literalSigilHeredocLine ::= heredocLinePrefix literalSigilBody EOL // literals can have escape sequences for escaped terminator literalSigilBody ::= (SIGIL_FRAGMENT | sigilEscapeSequence)* { implements = "org.elixir_lang.psi.Body" } - + literalStringSigilHeredoc ::= TILDE LITERAL_STRING_SIGIL_NAME STRING_SIGIL_HEREDOC_PROMOTER EOL literalStringHeredocLine* heredocPrefix STRING_SIGIL_HEREDOC_TERMINATOR sigilModifiers @@ -721,7 +721,7 @@ literalStringHeredocLine ::= heredocLinePrefix literalStringBody EOL // literals can have escape sequences for escaped terminator literalStringBody ::= (STRING_FRAGMENT | sigilEscapeSequence)* { implements = "org.elixir_lang.psi.Body" } - + literalWordsHeredoc ::= TILDE LITERAL_WORDS_SIGIL_NAME WORDS_HEREDOC_PROMOTER EOL literalWordsHeredocLine* heredocPrefix WORDS_HEREDOC_TERMINATOR sigilModifiers @@ -780,12 +780,14 @@ charListLine ::= CHAR_LIST_PROMOTER quoteCharListBody CHAR_LIST_TERMINATOR implements = [ "org.elixir_lang.psi.Atomable" "org.elixir_lang.psi.InterpolatedCharList" + "org.elixir_lang.psi.Line" "org.elixir_lang.psi.Quotable" ] methods = [ addEscapedCharacterCodePoints addFragmentCodePoints addHexadecimalEscapeSequenceCodePoints + getBody getFragmentType quote quoteAsAtom @@ -802,12 +804,14 @@ stringLine ::= STRING_PROMOTER quoteStringBody STRING_TERMINATOR implements = [ "org.elixir_lang.psi.Atomable" "org.elixir_lang.psi.InterpolatedString" + "org.elixir_lang.psi.Line" "org.elixir_lang.psi.Quotable" ] methods = [ addEscapedCharacterCodePoints addFragmentCodePoints addHexadecimalEscapeSequenceCodePoints + getBody getFragmentType quote quoteAsAtom diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index 66306e8b5..2d4fbd373 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -29,6 +29,7 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Comment", ElixirSyntaxHighlighter.COMMENT), new AttributesDescriptor("Decimal Exponent, Mark, and Separator", ElixirSyntaxHighlighter.DECIMAL), new AttributesDescriptor("Documentation Module Attributes", ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE), + new AttributesDescriptor("Documentation Text", ElixirSyntaxHighlighter.DOCUMENTATION_TEXT), new AttributesDescriptor("Escape Sequence", ElixirSyntaxHighlighter.VALID_ESCAPE_SEQUENCE), new AttributesDescriptor("Expression Substitution Mark", ElixirSyntaxHighlighter.EXPRESSION_SUBSTITUTION_MARK), new AttributesDescriptor("Identifier", ElixirSyntaxHighlighter.IDENTIFIER), diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index 38cc675cd..b74307c0f 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -59,6 +59,11 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { DefaultLanguageHighlighterColors.DOC_COMMENT_TAG ); + public static final TextAttributesKey DOCUMENTATION_TEXT = createTextAttributesKey( + "ELIXIR_DOCUMENTATION_TEXT", + DefaultLanguageHighlighterColors.DOC_COMMENT_TAG_VALUE + ); + public static final TextAttributesKey EXPRESSION_SUBSTITUTION_MARK = createTextAttributesKey( "ELIXIR_EXPRESSION_SUBSTITUTION_MARK", DefaultLanguageHighlighterColors.PARENTHESES diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index 68d8bb90c..310734751 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -11,13 +11,14 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiRecursiveElementVisitor; +import com.intellij.psi.tree.TokenSet; import org.elixir_lang.ElixirSyntaxHighlighter; -import org.elixir_lang.psi.AtUnqualifiedNoParenthesesCall; -import org.elixir_lang.psi.ElixirUnmatchedAtUnqualifiedNoParenthesesCall; -import org.elixir_lang.psi.Quotable; +import org.elixir_lang.psi.*; import org.elixir_lang.psi.impl.ElixirPsiImplUtil; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * Annotates module attributes. */ @@ -60,6 +61,8 @@ public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoPa identifier.equals("moduledoc") || identifier.equals("typedoc")) { highlight(textRange, holder, ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE); + + highlightDocumentationText(atUnqualifiedNoParenthesesCall, holder); } else { highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); } @@ -75,6 +78,50 @@ public void visitElement(@NotNull final PsiElement element) { ); } + private void highlightDocumentationText( + @NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + @NotNull final AnnotationHolder holder + ) { + PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); + PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); + + if (grandChildren.length == 1) { + PsiElement grandChild = grandChildren[0]; + + PsiElement[] greatGrandChildren = grandChild.getChildren(); + + if (greatGrandChildren.length == 1) { + PsiElement greatGrandChild = greatGrandChildren[0]; + + if (greatGrandChild instanceof Heredoc) { + Heredoc heredoc = (Heredoc) greatGrandChild; + List heredocLineList = heredoc.getHeredocLineList(); + + for (Bodied bodied : heredocLineList) { + Body body = bodied.getBody(); + + highlightFragments( + heredoc, + body, + holder, + ElixirSyntaxHighlighter.DOCUMENTATION_TEXT + ); + } + } else if (greatGrandChild instanceof Line) { + Line line = (Line) greatGrandChild; + Body body = line.getBody(); + + highlightFragments( + line, + body, + holder, + ElixirSyntaxHighlighter.DOCUMENTATION_TEXT + ); + } + } + } + } + /* * Private Instance Methods */ @@ -90,4 +137,30 @@ private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHo annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(TextAttributes.ERASE_MARKER); annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)); } + + /** + * Highlights fragment ASTNodes under `body` that have fragment type from `fragmented.getFragmentType()`. + * + * @param fragmented supplies fragment type + * @param body contains fragments + * @param annotationHolder the container which receives annotations created by the plugin. + * @param textAttributesKey text attributes to apply to the fragments. + */ + private void highlightFragments(@NotNull final Fragmented fragmented, + @NotNull final Body body, + @NotNull AnnotationHolder annotationHolder, + @NotNull final TextAttributesKey textAttributesKey) { + ASTNode bodyNode = body.getNode(); + ASTNode[] fragmentNodes = bodyNode.getChildren( + TokenSet.create(fragmented.getFragmentType()) + ); + + for (ASTNode fragmentNode : fragmentNodes) { + highlight( + fragmentNode.getTextRange(), + annotationHolder, + textAttributesKey + ); + } + } } diff --git a/src/org/elixir_lang/psi/Line.java b/src/org/elixir_lang/psi/Line.java index 5932749cc..b7bd873cd 100644 --- a/src/org/elixir_lang/psi/Line.java +++ b/src/org/elixir_lang/psi/Line.java @@ -5,5 +5,5 @@ * * Created by luke.imhoff on 2/27/15. */ -public interface Line { +public interface Line extends Bodied, Fragmented { } diff --git a/src/org/elixir_lang/psi/SigilLine.java b/src/org/elixir_lang/psi/SigilLine.java index 73103c433..c33dcb74a 100644 --- a/src/org/elixir_lang/psi/SigilLine.java +++ b/src/org/elixir_lang/psi/SigilLine.java @@ -3,6 +3,6 @@ /** * Created by luke.imhoff on 2/27/15. */ -public interface SigilLine extends Bodied, Line, Sigil { +public interface SigilLine extends Line, Sigil { char terminator(); } diff --git a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java index a13831015..c4e57df2d 100644 --- a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java +++ b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java @@ -1214,6 +1214,11 @@ public static Body getBody(ElixirCharListHeredocLine charListHeredocLine) { return charListHeredocLine.getQuoteCharListBody(); } + @NotNull + public static Body getBody(@NotNull final ElixirCharListLine charListLine) { + return charListLine.getQuoteCharListBody(); + } + public static Body getBody(ElixirInterpolatedCharListHeredocLine interpolatedCharListHeredocLine) { return interpolatedCharListHeredocLine.getInterpolatedCharListBody(); } @@ -1298,6 +1303,10 @@ public static Body getBody(ElixirStringHeredocLine stringHeredocLine) { return stringHeredocLine.getQuoteStringBody(); } + public static Body getBody(@NotNull final ElixirStringLine stringLine) { + return stringLine.getQuoteStringBody(); + } + @Contract(pure = true, value = "_ -> null") @Nullable public static ElixirDoBlock getDoBlock(@NotNull @SuppressWarnings("unused") final ElixirUnqualifiedNoParenthesesManyArgumentsCall unqualifiedNoParenthesesManyArgumentsCall) { @@ -1372,7 +1381,7 @@ public static List getHeredocLineList(ElixirInterpolatedRegexHeredo return heredocLineList; } - + public static List getHeredocLineList(ElixirInterpolatedSigilHeredoc interpolatedSigilHeredoc) { List interpolatedSigilHeredocLines = interpolatedSigilHeredoc.getInterpolatedSigilHeredocLineList(); List heredocLineList = new ArrayList(interpolatedSigilHeredocLines.size()); @@ -1427,7 +1436,7 @@ public static List getHeredocLineList(ElixirLiteralSigilHeredoc lit return heredocLineList; } - + public static List getHeredocLineList(ElixirLiteralStringSigilHeredoc literalStringSigilHeredoc) { List literalStringHeredocLines = literalStringSigilHeredoc.getLiteralStringHeredocLineList(); List heredocLineList = new ArrayList(literalStringHeredocLines.size()); @@ -1437,8 +1446,8 @@ public static List getHeredocLineList(ElixirLiteralStringSigilHered } return heredocLineList; - } - + } + public static List getHeredocLineList(ElixirLiteralWordsHeredoc literalWordsSigilHeredoc) { List literalWordsHeredocLines = literalWordsSigilHeredoc.getLiteralWordsHeredocLineList(); List heredocLineList = new ArrayList(literalWordsHeredocLines.size()); @@ -1449,7 +1458,7 @@ public static List getHeredocLineList(ElixirLiteralWordsHeredoc lit return heredocLineList; } - + public static List getHeredocLineList(ElixirStringHeredoc stringHeredoc) { List stringHeredocLineList = stringHeredoc.getStringHeredocLineList(); List heredocLineList = new ArrayList(stringHeredocLineList.size()); @@ -1727,7 +1736,7 @@ public static OtpErlangObject quoteAsAtom(@NotNull final ElixirCharListLine char return quotedAsAtom; } - + @Contract(pure = true) @NotNull public static OtpErlangObject quoteAsAtom(@NotNull final ElixirStringLine stringLine) { @@ -1749,7 +1758,7 @@ public static OtpErlangObject quoteAsAtom(@NotNull final ElixirStringLine string UTF_8 ); } - + return quotedAsAtom; } From 5f8acd34563e13cd3da33a553764132a7a83becc Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 10 Dec 2015 23:18:35 -0600 Subject: [PATCH 05/10] Weak warning on @doc/@moduledoc/@typedoc false --- src/org/elixir_lang/annonator/ModuleAttribute.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index 310734751..f775b867e 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -93,7 +93,16 @@ private void highlightDocumentationText( if (greatGrandChildren.length == 1) { PsiElement greatGrandChild = greatGrandChildren[0]; - if (greatGrandChild instanceof Heredoc) { + if (greatGrandChild instanceof ElixirAtomKeyword) { + ElixirAtomKeyword atomKeyword = (ElixirAtomKeyword) greatGrandChild; + String text = atomKeyword.getText(); + + if (text.equals("false")) { + holder.createWeakWarningAnnotation( + atomKeyword, + "Will make documented invisible to the documentation extraction tools like ExDoc."); + } + } else if (greatGrandChild instanceof Heredoc) { Heredoc heredoc = (Heredoc) greatGrandChild; List heredocLineList = heredoc.getHeredocLineList(); From f917d2b2cbce20813dc43c4c3704e32f0eb5a438 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Sat, 12 Dec 2015 21:30:16 -0600 Subject: [PATCH 06/10] Highlight callbacks The `@callback` will be highlighted as a "Module Attributes" while the name of the function itself will be highlighted as "Callbacks". --- .../ElixirContainerAssociationOperation.java | 9 + .../psi/ElixirMatchedAdditionOperation.java | 9 + .../psi/ElixirMatchedAndOperation.java | 9 + .../psi/ElixirMatchedArrowOperation.java | 9 + .../psi/ElixirMatchedComparisonOperation.java | 9 + .../psi/ElixirMatchedInMatchOperation.java | 9 + .../psi/ElixirMatchedInOperation.java | 9 + .../psi/ElixirMatchedMatchOperation.java | 9 + .../ElixirMatchedMultiplicationOperation.java | 9 + .../psi/ElixirMatchedOrOperation.java | 9 + .../psi/ElixirMatchedPipeOperation.java | 9 + .../psi/ElixirMatchedRelationalOperation.java | 9 + .../psi/ElixirMatchedTwoOperation.java | 9 + .../psi/ElixirMatchedTypeOperation.java | 9 + .../psi/ElixirMatchedWhenOperation.java | 9 + .../psi/ElixirUnmatchedAdditionOperation.java | 9 + .../psi/ElixirUnmatchedAndOperation.java | 9 + .../psi/ElixirUnmatchedArrowOperation.java | 9 + .../ElixirUnmatchedComparisonOperation.java | 9 + .../psi/ElixirUnmatchedInMatchOperation.java | 9 + .../psi/ElixirUnmatchedInOperation.java | 9 + .../psi/ElixirUnmatchedMatchOperation.java | 9 + ...lixirUnmatchedMultiplicationOperation.java | 9 + .../psi/ElixirUnmatchedOrOperation.java | 9 + .../psi/ElixirUnmatchedPipeOperation.java | 9 + .../ElixirUnmatchedRelationalOperation.java | 9 + .../psi/ElixirUnmatchedTwoOperation.java | 9 + .../psi/ElixirUnmatchedTypeOperation.java | 9 + .../psi/ElixirUnmatchedWhenOperation.java | 9 + ...ixirContainerAssociationOperationImpl.java | 20 +- .../ElixirMatchedAdditionOperationImpl.java | 20 +- .../impl/ElixirMatchedAndOperationImpl.java | 20 +- .../impl/ElixirMatchedArrowOperationImpl.java | 20 +- .../ElixirMatchedComparisonOperationImpl.java | 20 +- .../ElixirMatchedInMatchOperationImpl.java | 20 +- .../impl/ElixirMatchedInOperationImpl.java | 20 +- .../impl/ElixirMatchedMatchOperationImpl.java | 20 +- ...xirMatchedMultiplicationOperationImpl.java | 20 +- .../impl/ElixirMatchedOrOperationImpl.java | 20 +- .../impl/ElixirMatchedPipeOperationImpl.java | 20 +- .../ElixirMatchedRelationalOperationImpl.java | 20 +- .../impl/ElixirMatchedTwoOperationImpl.java | 20 +- .../impl/ElixirMatchedTypeOperationImpl.java | 20 +- .../impl/ElixirMatchedWhenOperationImpl.java | 20 +- .../ElixirUnmatchedAdditionOperationImpl.java | 20 +- .../impl/ElixirUnmatchedAndOperationImpl.java | 20 +- .../ElixirUnmatchedArrowOperationImpl.java | 20 +- ...lixirUnmatchedComparisonOperationImpl.java | 20 +- .../ElixirUnmatchedInMatchOperationImpl.java | 20 +- .../impl/ElixirUnmatchedInOperationImpl.java | 20 +- .../ElixirUnmatchedMatchOperationImpl.java | 20 +- ...rUnmatchedMultiplicationOperationImpl.java | 20 +- .../impl/ElixirUnmatchedOrOperationImpl.java | 20 +- .../ElixirUnmatchedPipeOperationImpl.java | 20 +- ...lixirUnmatchedRelationalOperationImpl.java | 20 +- .../impl/ElixirUnmatchedTwoOperationImpl.java | 20 +- .../ElixirUnmatchedTypeOperationImpl.java | 20 +- .../ElixirUnmatchedWhenOperationImpl.java | 20 +- src/org/elixir_lang/Elixir.bnf | 300 ++++++++++++++++-- .../elixir_lang/ElixirColorSettingsPage.java | 1 + .../elixir_lang/ElixirSyntaxHighlighter.java | 6 + .../annonator/ModuleAttribute.java | 64 ++-- src/org/elixir_lang/psi/InfixOperation.java | 4 +- .../psi/impl/ElixirPsiImplUtil.java | 70 ++-- 64 files changed, 1095 insertions(+), 191 deletions(-) diff --git a/gen/org/elixir_lang/psi/ElixirContainerAssociationOperation.java b/gen/org/elixir_lang/psi/ElixirContainerAssociationOperation.java index 405d9b371..293393fe8 100644 --- a/gen/org/elixir_lang/psi/ElixirContainerAssociationOperation.java +++ b/gen/org/elixir_lang/psi/ElixirContainerAssociationOperation.java @@ -14,7 +14,16 @@ public interface ElixirContainerAssociationOperation extends AssociationOperatio @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedAdditionOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedAdditionOperation.java index 15ad8e191..b68718e46 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedAdditionOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedAdditionOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedAdditionOperation extends ElixirMatchedExpression, @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedAndOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedAndOperation.java index 6860df1ec..6d5fa4d85 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedAndOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedAndOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedAndOperation extends ElixirMatchedExpression, Infi @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedArrowOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedArrowOperation.java index 5beaf4fc6..352f4e4b3 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedArrowOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedArrowOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedArrowOperation extends ElixirMatchedExpression, In @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedComparisonOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedComparisonOperation.java index f2d0ec541..d6ae3c915 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedComparisonOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedComparisonOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedComparisonOperation extends ElixirMatchedExpressio @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedInMatchOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedInMatchOperation.java index 26f089e25..a529c519f 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedInMatchOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedInMatchOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedInMatchOperation extends ElixirMatchedExpression, @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedInOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedInOperation.java index f24b102d3..ad7510cbb 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedInOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedInOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedInOperation extends ElixirMatchedExpression, InOpe @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedMatchOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedMatchOperation.java index dbbdb3228..4a19365b3 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedMatchOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedMatchOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedMatchOperation extends ElixirMatchedExpression, In @NotNull List getMatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedMultiplicationOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedMultiplicationOperation.java index d24a15640..c5213d342 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedMultiplicationOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedMultiplicationOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedMultiplicationOperation extends ElixirMatchedExpre @NotNull ElixirMultiplicationInfixOperator getMultiplicationInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedOrOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedOrOperation.java index e9634b05d..dbfa9ec30 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedOrOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedOrOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedOrOperation extends ElixirMatchedExpression, Infix @NotNull ElixirOrInfixOperator getOrInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedPipeOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedPipeOperation.java index ed251283b..b038f58df 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedPipeOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedPipeOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedPipeOperation extends ElixirMatchedExpression, Inf @NotNull ElixirPipeInfixOperator getPipeInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedRelationalOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedRelationalOperation.java index acb843d78..90a4c9575 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedRelationalOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedRelationalOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedRelationalOperation extends ElixirMatchedExpressio @NotNull ElixirRelationalInfixOperator getRelationalInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedTwoOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedTwoOperation.java index 32aa2ba3a..b8cc77f70 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedTwoOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedTwoOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedTwoOperation extends ElixirMatchedExpression, Infi @NotNull ElixirTwoInfixOperator getTwoInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedTypeOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedTypeOperation.java index d364aaa03..fed1ff691 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedTypeOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedTypeOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedTypeOperation extends ElixirMatchedExpression, Inf @NotNull ElixirTypeInfixOperator getTypeInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedWhenOperation.java b/gen/org/elixir_lang/psi/ElixirMatchedWhenOperation.java index 0bcddd659..477956943 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedWhenOperation.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedWhenOperation.java @@ -14,7 +14,16 @@ public interface ElixirMatchedWhenOperation extends ElixirMatchedExpression, Inf @NotNull ElixirWhenInfixOperator getWhenInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedAdditionOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedAdditionOperation.java index dc6431d6a..7c191cddc 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedAdditionOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedAdditionOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedAdditionOperation extends ElixirUnmatchedExpress @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedAndOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedAndOperation.java index 43765ab0c..262fef662 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedAndOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedAndOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedAndOperation extends ElixirUnmatchedExpression, @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedArrowOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedArrowOperation.java index ad7d4f42d..5d87802f8 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedArrowOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedArrowOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedArrowOperation extends ElixirUnmatchedExpression @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedComparisonOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedComparisonOperation.java index 7d040054f..8f7acc553 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedComparisonOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedComparisonOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedComparisonOperation extends ElixirUnmatchedExpre @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedInMatchOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedInMatchOperation.java index 609fbc441..a2db93515 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedInMatchOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedInMatchOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedInMatchOperation extends ElixirUnmatchedExpressi @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedInOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedInOperation.java index d11a328b8..91677f271 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedInOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedInOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedInOperation extends ElixirUnmatchedExpression, I @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedMatchOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedMatchOperation.java index 939ccdbaa..0d0de733e 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedMatchOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedMatchOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedMatchOperation extends ElixirUnmatchedExpression @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedMultiplicationOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedMultiplicationOperation.java index de0502e17..dd08a1df0 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedMultiplicationOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedMultiplicationOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedMultiplicationOperation extends ElixirUnmatchedE @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedOrOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedOrOperation.java index 15a6ae133..984ff8af5 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedOrOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedOrOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedOrOperation extends ElixirUnmatchedExpression, I @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedPipeOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedPipeOperation.java index eb1b417cf..b2d339c50 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedPipeOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedPipeOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedPipeOperation extends ElixirUnmatchedExpression, @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedRelationalOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedRelationalOperation.java index 0e47dc753..daf4bade7 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedRelationalOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedRelationalOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedRelationalOperation extends ElixirUnmatchedExpre @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedTwoOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedTwoOperation.java index a86772772..43f980c00 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedTwoOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedTwoOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedTwoOperation extends ElixirUnmatchedExpression, @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedTypeOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedTypeOperation.java index 325786a13..c7446cb24 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedTypeOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedTypeOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedTypeOperation extends ElixirUnmatchedExpression, @NotNull List getUnmatchedExpressionList(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedWhenOperation.java b/gen/org/elixir_lang/psi/ElixirUnmatchedWhenOperation.java index f3eae3e34..1e8412e18 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedWhenOperation.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedWhenOperation.java @@ -14,7 +14,16 @@ public interface ElixirUnmatchedWhenOperation extends ElixirUnmatchedExpression, @NotNull ElixirWhenInfixOperator getWhenInfixOperator(); + @NotNull + Quotable leftOperand(); + + @NotNull + Operator operator(); + @NotNull OtpErlangObject quote(); + @NotNull + Quotable rightOperand(); + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirContainerAssociationOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirContainerAssociationOperationImpl.java index 882e7aeba..617f1e8d7 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirContainerAssociationOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirContainerAssociationOperationImpl.java @@ -6,10 +6,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirContainerAssociationOperation; -import org.elixir_lang.psi.ElixirEmptyParentheses; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -37,9 +34,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedAdditionOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedAdditionOperationImpl.java index 60124e4ba..de8ec39d3 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedAdditionOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedAdditionOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirAdditionInfixOperator; -import org.elixir_lang.psi.ElixirMatchedAdditionOperation; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedAndOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedAndOperationImpl.java index 2945e3266..709499c99 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedAndOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedAndOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirAndInfixOperator; -import org.elixir_lang.psi.ElixirMatchedAndOperation; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedArrowOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedArrowOperationImpl.java index 37e39ba0e..8e7149042 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedArrowOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedArrowOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirArrowInfixOperator; -import org.elixir_lang.psi.ElixirMatchedArrowOperation; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedComparisonOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedComparisonOperationImpl.java index 8106fb41d..18c49744d 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedComparisonOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedComparisonOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirComparisonInfixOperator; -import org.elixir_lang.psi.ElixirMatchedComparisonOperation; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedInMatchOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedInMatchOperationImpl.java index e517524fc..dc2accf6f 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedInMatchOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedInMatchOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirInMatchInfixOperator; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedInMatchOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedInOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedInOperationImpl.java index dc4f67ff9..705c8658a 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedInOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedInOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirInInfixOperator; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedInOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedMatchOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedMatchOperationImpl.java index fad8daa96..c7d4257f7 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedMatchOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedMatchOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchInfixOperator; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedMatchOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getMatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirMatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedMultiplicationOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedMultiplicationOperationImpl.java index 5aa0e7706..00b3aa80f 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedMultiplicationOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedMultiplicationOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedMultiplicationOperation; -import org.elixir_lang.psi.ElixirMultiplicationInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirMultiplicationInfixOperator getMultiplicationInfixOperator() { return findNotNullChildByClass(ElixirMultiplicationInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedOrOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedOrOperationImpl.java index b51757529..c0ef9bbd2 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedOrOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedOrOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedOrOperation; -import org.elixir_lang.psi.ElixirOrInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirOrInfixOperator getOrInfixOperator() { return findNotNullChildByClass(ElixirOrInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedPipeOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedPipeOperationImpl.java index 65989c8a1..385f7ce62 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedPipeOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedPipeOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedPipeOperation; -import org.elixir_lang.psi.ElixirPipeInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirPipeInfixOperator getPipeInfixOperator() { return findNotNullChildByClass(ElixirPipeInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedRelationalOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedRelationalOperationImpl.java index a4c5afa2a..66c4f6fd2 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedRelationalOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedRelationalOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedRelationalOperation; -import org.elixir_lang.psi.ElixirRelationalInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirRelationalInfixOperator getRelationalInfixOperator() { return findNotNullChildByClass(ElixirRelationalInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedTwoOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedTwoOperationImpl.java index a2994c02d..1f4c9ca24 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedTwoOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedTwoOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedTwoOperation; -import org.elixir_lang.psi.ElixirTwoInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirTwoInfixOperator getTwoInfixOperator() { return findNotNullChildByClass(ElixirTwoInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedTypeOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedTypeOperationImpl.java index 8e31277f1..8bbf172cd 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedTypeOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedTypeOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedTypeOperation; -import org.elixir_lang.psi.ElixirTypeInfixOperator; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirTypeInfixOperator getTypeInfixOperator() { return findNotNullChildByClass(ElixirTypeInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedWhenOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedWhenOperationImpl.java index e2b6b9748..56707ab55 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedWhenOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedWhenOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchedExpression; -import org.elixir_lang.psi.ElixirMatchedWhenOperation; -import org.elixir_lang.psi.ElixirVisitor; -import org.elixir_lang.psi.ElixirWhenInfixOperator; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirWhenInfixOperator getWhenInfixOperator() { return findNotNullChildByClass(ElixirWhenInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAdditionOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAdditionOperationImpl.java index 24751f0d8..ac3cabf60 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAdditionOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAdditionOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirAdditionInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedAdditionOperation; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAndOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAndOperationImpl.java index 18230cd17..2f956f05d 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAndOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAndOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirAndInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedAndOperation; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedArrowOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedArrowOperationImpl.java index c872ba27b..0c7b0b405 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedArrowOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedArrowOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirArrowInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedArrowOperation; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedComparisonOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedComparisonOperationImpl.java index 0629f442b..e9f9fe62f 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedComparisonOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedComparisonOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirComparisonInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedComparisonOperation; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInMatchOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInMatchOperationImpl.java index 85728d560..62d1f61e1 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInMatchOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInMatchOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirInMatchInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedInMatchOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInOperationImpl.java index 6c02ee701..ed85c4054 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedInOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirInInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedInOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMatchOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMatchOperationImpl.java index 8e363cafe..6a7d38f89 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMatchOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMatchOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMatchInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedMatchOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMultiplicationOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMultiplicationOperationImpl.java index dc089705b..7554d0d7c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMultiplicationOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedMultiplicationOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirMultiplicationInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedMultiplicationOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedOrOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedOrOperationImpl.java index 267e6d363..20fd94025 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedOrOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedOrOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirOrInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedOrOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedPipeOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedPipeOperationImpl.java index 9b4e0e78c..a19ca68bd 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedPipeOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedPipeOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirPipeInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedPipeOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedRelationalOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedRelationalOperationImpl.java index 51820aacb..578b9799c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedRelationalOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedRelationalOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirRelationalInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedRelationalOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTwoOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTwoOperationImpl.java index 27fa21f54..fe650c44c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTwoOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTwoOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirTwoInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedTwoOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTypeOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTypeOperationImpl.java index 3104646d0..dc06367f5 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTypeOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedTypeOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirTypeInfixOperator; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedTypeOperation; -import org.elixir_lang.psi.ElixirVisitor; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public List getUnmatchedExpressionList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, ElixirUnmatchedExpression.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedWhenOperationImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedWhenOperationImpl.java index f17e734b4..b12dd881e 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedWhenOperationImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedWhenOperationImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import org.elixir_lang.psi.ElixirUnmatchedExpression; -import org.elixir_lang.psi.ElixirUnmatchedWhenOperation; -import org.elixir_lang.psi.ElixirVisitor; -import org.elixir_lang.psi.ElixirWhenInfixOperator; +import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,9 +33,24 @@ public ElixirWhenInfixOperator getWhenInfixOperator() { return findNotNullChildByClass(ElixirWhenInfixOperator.class); } + @NotNull + public Quotable leftOperand() { + return ElixirPsiImplUtil.leftOperand(this); + } + + @NotNull + public Operator operator() { + return ElixirPsiImplUtil.operator(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); } + @NotNull + public Quotable rightOperand() { + return ElixirPsiImplUtil.rightOperand(this); + } + } diff --git a/src/org/elixir_lang/Elixir.bnf b/src/org/elixir_lang/Elixir.bnf index dd1fa25b9..69ff36fc5 100644 --- a/src/org/elixir_lang/Elixir.bnf +++ b/src/org/elixir_lang/Elixir.bnf @@ -1124,7 +1124,15 @@ inMatchInfixOperator ::= EOL* IN_MATCH_OPERATOR EOL* name = "<-, \\\\" } matchedInMatchOperation ::= matchedExpression inMatchInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * When Operation - right-associative @@ -1150,7 +1158,16 @@ whenInfixOperator ::= EOL* WHEN_OPERATOR EOL* matchedWhenNoParenthesesKeywordsOperation ::= matchedExpression whenInfixOperator noParenthesesKeywords { elementType = matchedWhenOperation rightAssociative = true } matchedWhenOperation ::= matchedExpression whenInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Type Operation - right-associative @@ -1168,7 +1185,16 @@ typeInfixOperator ::= EOL* TYPE_OPERATOR EOL* name = "::" } matchedTypeOperation ::= matchedExpression typeInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Pipe Operation - right-associative @@ -1186,7 +1212,16 @@ pipeInfixOperator ::= EOL* PIPE_OPERATOR EOL* name = "|" } matchedPipeOperation ::= matchedExpression pipeInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Match Operation - right-associative @@ -1204,7 +1239,16 @@ matchInfixOperator ::= EOL* MATCH_OPERATOR EOL* name = "=" } matchedMatchOperation ::= matchedExpression matchInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Or Operation - left-associative @@ -1222,7 +1266,15 @@ orInfixOperator ::= EOL* OR_OPERATOR EOL* name = "||, |||, or" } matchedOrOperation ::= matchedExpression orInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * And Operation - left-associative @@ -1239,7 +1291,15 @@ andInfixOperator ::= EOL* AND_OPERATOR EOL* name = "&&, &&&, and" } matchedAndOperation ::= matchedExpression andInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Comparison Operation - left-associative @@ -1257,7 +1317,15 @@ comparisonInfixOperator ::= EOL* COMPARISON_OPERATOR EOL* name = "!=, ==, =~, !==, ===" } matchedComparisonOperation ::= matchedExpression comparisonInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Relational Operation - left-associative @@ -1275,7 +1343,15 @@ relationalInfixOperator ::= EOL* RELATIONAL_OPERATOR EOL* name = "<, >, <=, >=" } matchedRelationalOperation ::= matchedExpression relationalInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Arrow Operation - left-associative @@ -1293,7 +1369,15 @@ arrowInfixOperator ::= EOL* ARROW_OPERATOR EOL* name = "<~, |>, ~>, <<<, <<~, <|>, <~>, >>>, ~>>, ^^^" } matchedArrowOperation ::= matchedExpression arrowInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * In Operation - left-associative @@ -1311,7 +1395,15 @@ inInfixOperator ::= EOL* IN_OPERATOR EOL* name = "in" } matchedInOperation ::= matchedExpression inInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Two Operation - right-associative @@ -1329,7 +1421,16 @@ twoInfixOperator ::= EOL* TWO_OPERATOR EOL* name = "++, --, .., <>" } matchedTwoOperation ::= matchedExpression twoInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Addition Operation - left-associative @@ -1354,7 +1455,15 @@ additionInfixOperator ::= (SIGNIFICANT_WHITE_SPACE DUAL_OPERATOR (SIGNIFICANT_WH name = "+, -" } matchedAdditionOperation ::= matchedExpression additionInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* @@ -1374,7 +1483,15 @@ multiplicationInfixOperator ::= EOL* MULTIPLICATION_OPERATOR EOL* name = "*, /" } matchedMultiplicationOperation ::= matchedExpression multiplicationInfixOperator matchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Unary Non-Numeric Operation - non-associative @@ -1824,7 +1941,15 @@ private associationInfixOperator ::= EOL* ASSOCIATION_OPERATOR EOL* // @see https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L505 containerAssociationOperation ::= containerExpression associationInfixOperator containerExpression - { implements = "org.elixir_lang.psi.AssociationOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.AssociationOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } left maxDotCall ::= dotInfixOperator parenthesesArguments parenthesesArguments? { elementType = matchedDotCall } @@ -2111,7 +2236,15 @@ unmatchedCaptureNonNumericOperation ::= capturePrefixOperator !numeric unmatched */ unmatchedInMatchOperation ::= unmatchedExpression inMatchInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * When Operation - right-associative @@ -2128,7 +2261,16 @@ unmatchedInMatchOperation ::= unmatchedExpression inMatchInfixOperator unmatched unmatchedWhenNoParenthesesKeywordsOperation ::= unmatchedExpression whenInfixOperator noParenthesesKeywords { elementType = unmatchedWhenOperation rightAssociative = true } unmatchedWhenOperation ::= unmatchedExpression whenInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Type Operation - right-associative @@ -2137,7 +2279,16 @@ unmatchedWhenOperation ::= unmatchedExpression whenInfixOperator unmatchedExpres */ unmatchedTypeOperation ::= unmatchedExpression typeInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Pipe Operation - right-associative @@ -2146,7 +2297,16 @@ unmatchedTypeOperation ::= unmatchedExpression typeInfixOperator unmatchedExpres */ unmatchedPipeOperation ::= unmatchedExpression pipeInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Match Operation - right-associative @@ -2156,7 +2316,16 @@ unmatchedPipeOperation ::= unmatchedExpression pipeInfixOperator unmatchedExpres unmatchedMatchOperation ::= unmatchedExpression matchInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Or Operation - left-associative @@ -2165,7 +2334,15 @@ unmatchedMatchOperation ::= unmatchedExpression matchInfixOperator unmatchedExpr */ unmatchedOrOperation ::= unmatchedExpression orInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * And Operation - left-associative @@ -2174,7 +2351,15 @@ unmatchedOrOperation ::= unmatchedExpression orInfixOperator unmatchedExpression */ unmatchedAndOperation ::= unmatchedExpression andInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Comparison Operation - left-associative @@ -2183,7 +2368,15 @@ unmatchedAndOperation ::= unmatchedExpression andInfixOperator unmatchedExpressi */ unmatchedComparisonOperation ::= unmatchedExpression comparisonInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Relational Operation - left-associative @@ -2192,7 +2385,15 @@ unmatchedComparisonOperation ::= unmatchedExpression comparisonInfixOperator unm */ unmatchedRelationalOperation ::= unmatchedExpression relationalInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Arrow Operation - left-associative @@ -2201,7 +2402,15 @@ unmatchedRelationalOperation ::= unmatchedExpression relationalInfixOperator unm */ unmatchedArrowOperation ::= unmatchedExpression arrowInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * In Operation - left-associative @@ -2210,7 +2419,15 @@ unmatchedArrowOperation ::= unmatchedExpression arrowInfixOperator unmatchedExpr */ unmatchedInOperation ::= unmatchedExpression inInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Two Operation - right-associative @@ -2219,7 +2436,16 @@ unmatchedInOperation ::= unmatchedExpression inInfixOperator unmatchedExpression */ unmatchedTwoOperation ::= unmatchedExpression twoInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] rightAssociative = true } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + rightAssociative = true + } /* * Addition Operation - left-associative @@ -2229,7 +2455,15 @@ unmatchedTwoOperation ::= unmatchedExpression twoInfixOperator unmatchedExpressi */ unmatchedAdditionOperation ::= unmatchedExpression additionInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Multiplication Operation - left-associative @@ -2239,7 +2473,15 @@ unmatchedAdditionOperation ::= unmatchedExpression additionInfixOperator unmatch */ unmatchedMultiplicationOperation ::= unmatchedExpression multiplicationInfixOperator unmatchedExpression - { implements = "org.elixir_lang.psi.InfixOperation" methods = [quote] } + { + implements = "org.elixir_lang.psi.InfixOperation" + methods = [ + leftOperand + operator + quote + rightOperand + ] + } /* * Unary Non-Numeric Operation - non-associative diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index 2d4fbd373..d383cbd8f 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -24,6 +24,7 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Alias", ElixirSyntaxHighlighter.ALIAS), new AttributesDescriptor("Atom", ElixirSyntaxHighlighter.ATOM), new AttributesDescriptor("Binary, Decimal, Hexadecimal, and Octal Digits", ElixirSyntaxHighlighter.VALID_DIGIT), + new AttributesDescriptor("Callback", ElixirSyntaxHighlighter.CALLBACK), new AttributesDescriptor("Character List", ElixirSyntaxHighlighter.CHAR_LIST), new AttributesDescriptor("Character Token", ElixirSyntaxHighlighter.CHAR_TOKEN_TOKEN), new AttributesDescriptor("Comment", ElixirSyntaxHighlighter.COMMENT), diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index b74307c0f..186f865f8 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -34,6 +34,12 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { HighlighterColors.BAD_CHARACTER ); + public static final TextAttributesKey CALLBACK = createTextAttributesKey( + "ELIXIR_CALLBACK", + // matches ERL_CALLBACK + CodeInsightColors.METHOD_CALL_ATTRIBUTES + ); + public static final TextAttributesKey CHAR_LIST = createTextAttributesKey( "ELIXIR_CHAR_LIST", DefaultLanguageHighlighterColors.STRING diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index f775b867e..4dfd77417 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -5,7 +5,6 @@ import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; @@ -14,6 +13,7 @@ import com.intellij.psi.tree.TokenSet; import org.elixir_lang.ElixirSyntaxHighlighter; import org.elixir_lang.psi.*; +import org.elixir_lang.psi.call.Call; import org.elixir_lang.psi.impl.ElixirPsiImplUtil; import org.jetbrains.annotations.NotNull; @@ -54,10 +54,13 @@ public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoPa identifierNode.getTextRange().getEndOffset() ); - String identifier = identifierNode.getText(); - if (identifier.equals("doc") || + if (identifier.equals("callback") || identifier.equals("macrocallback")) { + highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + + highlightCallback(atUnqualifiedNoParenthesesCall, holder); + } else if (identifier.equals("doc") || identifier.equals("moduledoc") || identifier.equals("typedoc")) { highlight(textRange, holder, ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE); @@ -78,6 +81,45 @@ public void visitElement(@NotNull final PsiElement element) { ); } + /* + * Private Instance Methods + */ + + /** + * Highlights `textRange` with the given `textAttributesKey`. + * + * @param textRange textRange in the document to highlight + * @param annotationHolder the container which receives annotations created by the plugin. + * @param textAttributesKey text attributes to apply to the `node`. + */ + private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHolder annotationHolder, @NotNull final TextAttributesKey textAttributesKey) { + annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(TextAttributes.ERASE_MARKER); + annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)); + } + + private void highlightCallback(@NotNull AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, AnnotationHolder annotationHolder) { + PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); + PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); + + if (grandChildren.length == 1) { + PsiElement grandChild = grandChildren[0]; + + if (grandChild instanceof ElixirMatchedTypeOperation) { + InfixOperation infixOperation = (InfixOperation) grandChild; + PsiElement leftOperand = infixOperation.leftOperand(); + + if (leftOperand instanceof Call) { + Call call = (Call) leftOperand; + ASTNode functionNameNode = call.functionNameNode(); + + if (functionNameNode != null) { + highlight(functionNameNode.getTextRange(), annotationHolder, ElixirSyntaxHighlighter.CALLBACK); + } + } + } + } + } + private void highlightDocumentationText( @NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, @NotNull final AnnotationHolder holder @@ -131,22 +173,6 @@ private void highlightDocumentationText( } } - /* - * Private Instance Methods - */ - - /** - * Highlights `textRange` with the given `textAttributesKey`. - * - * @param textRange textRange in the document to highlight - * @param annotationHolder the container which receives annotations created by the plugin. - * @param textAttributesKey text attributes to apply to the `node`. - */ - private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHolder annotationHolder, @NotNull final TextAttributesKey textAttributesKey) { - annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(TextAttributes.ERASE_MARKER); - annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)); - } - /** * Highlights fragment ASTNodes under `body` that have fragment type from `fragmented.getFragmentType()`. * diff --git a/src/org/elixir_lang/psi/InfixOperation.java b/src/org/elixir_lang/psi/InfixOperation.java index 085ff25a8..25fea4206 100644 --- a/src/org/elixir_lang/psi/InfixOperation.java +++ b/src/org/elixir_lang/psi/InfixOperation.java @@ -6,5 +6,7 @@ * Created by luke.imhoff on 3/18/15. */ public interface InfixOperation extends Quotable { - + Operator operator(); + Quotable leftOperand(); + Quotable rightOperand(); } diff --git a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java index c4e57df2d..8dc953d27 100644 --- a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java +++ b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java @@ -506,6 +506,16 @@ public static boolean isUnquoted(PsiElement element) { return unquoted; } + @Contract(pure = true) + @NotNull + public static Quotable leftOperand(InfixOperation infixOperation) { + PsiElement[] children = infixOperation.getChildren(); + + assert children.length == 3; + + return (Quotable) children[0]; + } + /* Returns the 0-indexed line number for the element */ public static int lineNumber(ASTNode node) { return document(node.getPsi()).getLineNumber(node.getStartOffset()); @@ -575,6 +585,16 @@ public static String moduleName(@NotNull final Qualified qualified) { return qualified.getFirstChild().getText(); } + @Contract(pure = true) + @NotNull + public static Operator operator(InfixOperation infixOperation) { + PsiElement[] children = infixOperation.getChildren(); + + assert children.length == 3; + + return (Operator) children[1]; + } + @Contract(pure = true) @NotNull public static ASTNode operatorTokenNode(@NotNull Operator operator) { @@ -814,9 +834,21 @@ public static OtpErlangObject quote(@NotNull final AssociationOperation associat @Contract(pure = true) @NotNull public static OtpErlangObject quote(@NotNull final InfixOperation infixOperation) { - PsiElement[] children = infixOperation.getChildren(); + Quotable leftOperand = infixOperation.leftOperand(); + OtpErlangObject quotedLeftOperand = leftOperand.quote(); + + Operator operator = infixOperation.operator(); + OtpErlangObject quotedOperator = operator.quote(); + + Quotable rightOperand = infixOperation.rightOperand(); + OtpErlangObject quotedRightOperand = rightOperand.quote(); - return quoteInfixOperationChildren(children); + return quotedFunctionCall( + quotedOperator, + metadata(operator), + quotedLeftOperand, + quotedRightOperand + ); } @Contract(pure = true) @@ -3370,30 +3402,6 @@ public static OtpErlangTuple quotedFunctionCall(final OtpErlangObject quotedQual ); } - @Contract(pure = true) - @NotNull - private static OtpErlangObject quoteInfixOperationChildren(PsiElement... children) { - if (children.length != 3) { - throw new NotImplementedException("BinaryOperation expected to have 3 children (left operand, operator, right operand"); - } - - Quotable leftOperand = (Quotable) children[0]; - OtpErlangObject quotedLeftOperand = leftOperand.quote(); - - Operator operator = (Operator) children[1]; - OtpErlangObject quotedOperator = operator.quote(); - - Quotable rightOperand = (Quotable) children[2]; - OtpErlangObject quotedRightOperand = rightOperand.quote(); - - return quotedFunctionCall( - quotedOperator, - metadata(operator), - quotedLeftOperand, - quotedRightOperand - ); - } - @Contract(pure = true) @NotNull public static OtpErlangObject quotedVariable(@NotNull final PsiElement variable) { @@ -3553,6 +3561,16 @@ public static String resolvedModuleName(@NotNull @SuppressWarnings("unused") fin return "Elixir.Kernel"; } + @Contract(pure = true) + @NotNull + public static Quotable rightOperand(InfixOperation infixOperation) { + PsiElement[] children = infixOperation.getChildren(); + + assert children.length == 3; + + return (Quotable) children[2]; + } + @NotNull public static PsiElement setName(@NotNull PsiElement element, @NotNull String newName) { return null; From 9d25755117cb8e31a3368b2164d36c9d954b0be0 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Sun, 13 Dec 2015 16:42:20 -0600 Subject: [PATCH 07/10] Highlight name of type as "Type" --- .../elixir_lang/ElixirColorSettingsPage.java | 3 +- .../elixir_lang/ElixirSyntaxHighlighter.java | 8 +++++ .../annonator/ModuleAttribute.java | 31 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index d383cbd8f..de8d015f9 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -43,7 +43,8 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Obsolete Non-Decimal Base Prefix", ElixirSyntaxHighlighter.OBSOLETE_WHOLE_NUMBER_BASE), new AttributesDescriptor("Operation Sign", ElixirSyntaxHighlighter.OPERATION_SIGN), new AttributesDescriptor("Sigil", ElixirSyntaxHighlighter.SIGIL), - new AttributesDescriptor("String", ElixirSyntaxHighlighter.STRING) + new AttributesDescriptor("String", ElixirSyntaxHighlighter.STRING), + new AttributesDescriptor("Type", ElixirSyntaxHighlighter.TYPE) }; @Nullable diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index 186f865f8..ad32dc897 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -10,6 +10,8 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.xmlb.annotations.Text; +import com.thaiopensource.xml.dtd.om.Def; +import org.apache.xmlbeans.impl.xb.ltgfmt.Code; import org.elixir_lang.psi.ElixirTypes; import org.jetbrains.annotations.NotNull; @@ -132,6 +134,12 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { DefaultLanguageHighlighterColors.STRING ); + public static final TextAttributesKey TYPE = createTextAttributesKey( + "ELIXIR_TYPE", + // matches ERL_TYPE + CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES + ); + public static final TextAttributesKey VALID_DIGIT = createTextAttributesKey( "ELIXIR_VALID_DIGIT", DefaultLanguageHighlighterColors.NUMBER diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index 4dfd77417..06eaa7b0f 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -66,6 +66,13 @@ public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoPa highlight(textRange, holder, ElixirSyntaxHighlighter.DOCUMENTATION_MODULE_ATTRIBUTE); highlightDocumentationText(atUnqualifiedNoParenthesesCall, holder); + } else if (identifier.equals("opaque") || + identifier.equals("type") || + identifier.equals("typep")) { + highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + + + highlightType(atUnqualifiedNoParenthesesCall, holder); } else { highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); } @@ -198,4 +205,28 @@ private void highlightFragments(@NotNull final Fragmented fragmented, ); } } + + private void highlightType(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + AnnotationHolder annotationHolder) { + PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); + PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); + + if (grandChildren.length == 1) { + PsiElement grandChild = grandChildren[0]; + + if (grandChild instanceof ElixirMatchedTypeOperation) { + InfixOperation infixOperation = (InfixOperation) grandChild; + PsiElement leftOperand = infixOperation.leftOperand(); + + if (leftOperand instanceof Call) { + Call call = (Call) leftOperand; + ASTNode functionNameNode = call.functionNameNode(); + + if (functionNameNode != null) { + highlight(functionNameNode.getTextRange(), annotationHolder, ElixirSyntaxHighlighter.TYPE); + } + } + } + } + } } From f205de254d7219c6daec8e7d9fe36118398f6f1b Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Sun, 13 Dec 2015 17:42:29 -0600 Subject: [PATCH 08/10] Highlight spec and function name spec is a "Module Attribute". Function name is "Specification". "Callback" now inherits from "Specification" since @callback uses the @spec format. --- .../elixir_lang/ElixirColorSettingsPage.java | 1 + .../elixir_lang/ElixirSyntaxHighlighter.java | 16 ++-- .../annonator/ModuleAttribute.java | 74 +++++++++++++------ 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index de8d015f9..5d9d0d36c 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -43,6 +43,7 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Obsolete Non-Decimal Base Prefix", ElixirSyntaxHighlighter.OBSOLETE_WHOLE_NUMBER_BASE), new AttributesDescriptor("Operation Sign", ElixirSyntaxHighlighter.OPERATION_SIGN), new AttributesDescriptor("Sigil", ElixirSyntaxHighlighter.SIGIL), + new AttributesDescriptor("Specification", ElixirSyntaxHighlighter.SPECIFICATION), new AttributesDescriptor("String", ElixirSyntaxHighlighter.STRING), new AttributesDescriptor("Type", ElixirSyntaxHighlighter.TYPE) }; diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index ad32dc897..ecae87b34 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -36,12 +36,6 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { HighlighterColors.BAD_CHARACTER ); - public static final TextAttributesKey CALLBACK = createTextAttributesKey( - "ELIXIR_CALLBACK", - // matches ERL_CALLBACK - CodeInsightColors.METHOD_CALL_ATTRIBUTES - ); - public static final TextAttributesKey CHAR_LIST = createTextAttributesKey( "ELIXIR_CHAR_LIST", DefaultLanguageHighlighterColors.STRING @@ -129,6 +123,16 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { DefaultLanguageHighlighterColors.TEMPLATE_LANGUAGE_COLOR ); + public static final TextAttributesKey SPECIFICATION = createTextAttributesKey( + "ELIXIR_SPECIFICATION", + CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES + ); + + public static final TextAttributesKey CALLBACK = createTextAttributesKey( + "ELIXIR_CALLBACK", + SPECIFICATION + ); + public static final TextAttributesKey STRING = createTextAttributesKey( "ELIXIR_STRING", DefaultLanguageHighlighterColors.STRING diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index 06eaa7b0f..95f3de400 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -3,6 +3,7 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; @@ -71,8 +72,11 @@ public void visitAtUnqualifiedNoParenthesesCall(@NotNull final AtUnqualifiedNoPa identifier.equals("typep")) { highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); - highlightType(atUnqualifiedNoParenthesesCall, holder); + } else if (identifier.equals("spec")) { + highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); + + highlightSpecification(atUnqualifiedNoParenthesesCall, holder); } else { highlight(textRange, holder, ElixirSyntaxHighlighter.MODULE_ATTRIBUTE); } @@ -104,27 +108,9 @@ private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHo annotationHolder.createInfoAnnotation(textRange, null).setEnforcedTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)); } - private void highlightCallback(@NotNull AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, AnnotationHolder annotationHolder) { - PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); - PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); - - if (grandChildren.length == 1) { - PsiElement grandChild = grandChildren[0]; - - if (grandChild instanceof ElixirMatchedTypeOperation) { - InfixOperation infixOperation = (InfixOperation) grandChild; - PsiElement leftOperand = infixOperation.leftOperand(); - - if (leftOperand instanceof Call) { - Call call = (Call) leftOperand; - ASTNode functionNameNode = call.functionNameNode(); - - if (functionNameNode != null) { - highlight(functionNameNode.getTextRange(), annotationHolder, ElixirSyntaxHighlighter.CALLBACK); - } - } - } - } + private void highlightCallback(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + @NotNull final AnnotationHolder annotationHolder) { + highlightSpecification(atUnqualifiedNoParenthesesCall, annotationHolder, ElixirSyntaxHighlighter.CALLBACK); } private void highlightDocumentationText( @@ -206,6 +192,50 @@ private void highlightFragments(@NotNull final Fragmented fragmented, } } + /** + * Highlights the function call name as a `ElixirSyntaxHighlighter.SPECIFICATION + * + * @param atUnqualifiedNoParenthesesCall + * @param annotationHolder + */ + private void highlightSpecification(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + @NotNull final AnnotationHolder annotationHolder) { + highlightSpecification(atUnqualifiedNoParenthesesCall, annotationHolder, ElixirSyntaxHighlighter.SPECIFICATION); + } + + /** + * Highlight the function call name using the given `textAttributesKey` + * + * @param atUnqualifiedNoParenthesesCall + * @param annotationHolder + * @param textAttributesKey + */ + private void highlightSpecification(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + @NotNull final AnnotationHolder annotationHolder, + @NotNull final TextAttributesKey textAttributesKey) { + PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); + PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); + + if (grandChildren.length == 1) { + PsiElement grandChild = grandChildren[0]; + + if (grandChild instanceof ElixirMatchedTypeOperation) { + InfixOperation infixOperation = (InfixOperation) grandChild; + PsiElement leftOperand = infixOperation.leftOperand(); + + if (leftOperand instanceof Call) { + Call call = (Call) leftOperand; + ASTNode functionNameNode = call.functionNameNode(); + + if (functionNameNode != null) { + highlight(functionNameNode.getTextRange(), annotationHolder, textAttributesKey); + } + } + } + } + } + + private void highlightType(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, AnnotationHolder annotationHolder) { PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); From 5e7113350fd99b166a923c23b6c4794ab5e4cf03 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 24 Dec 2015 14:37:39 -0600 Subject: [PATCH 09/10] Highlight Type Parameters In @type, @typep, and @opaque, arguments to the type name are Type Parameters that can be filled in later when the type is used. The type parameters appear in the definition of the type. For @spec and @callback, since the argument slots are already used for just the types of the parameters, the type parameters are supplied as keyword keys in a when clause. --- .../psi/ElixirMapConstructionArguments.java | 4 + ...MatchedAtUnqualifiedNoParenthesesCall.java | 7 + .../elixir_lang/psi/ElixirMatchedDotCall.java | 7 + ...ElixirMatchedQualifiedNoArgumentsCall.java | 7 + ...ixirMatchedQualifiedNoParenthesesCall.java | 7 + ...ElixirMatchedQualifiedParenthesesCall.java | 7 + ...ixirMatchedUnqualifiedNoArgumentsCall.java | 7 + ...irMatchedUnqualifiedNoParenthesesCall.java | 7 + ...ixirMatchedUnqualifiedParenthesesCall.java | 7 + .../psi/ElixirNoParenthesesManyArguments.java | 6 +- ...nyPositionalAndMaybeKeywordsArguments.java | 6 +- .../psi/ElixirNoParenthesesOneArgument.java | 5 +- ...esesOnePositionalAndKeywordsArguments.java | 6 +- .../psi/ElixirNoParenthesesStrict.java | 6 +- .../psi/ElixirParenthesesArguments.java | 6 +- ...matchedAtUnqualifiedNoParenthesesCall.java | 7 + .../psi/ElixirUnmatchedDotCall.java | 7 + ...ixirUnmatchedQualifiedNoArgumentsCall.java | 7 + ...irUnmatchedQualifiedNoParenthesesCall.java | 7 + ...ixirUnmatchedQualifiedParenthesesCall.java | 7 + ...irUnmatchedUnqualifiedNoArgumentsCall.java | 7 + ...UnmatchedUnqualifiedNoParenthesesCall.java | 6 + ...irUnmatchedUnqualifiedParenthesesCall.java | 7 + ...alifiedNoParenthesesManyArgumentsCall.java | 9 +- gen/org/elixir_lang/psi/ElixirVisitor.java | 23 +- .../ElixirMapConstructionArgumentsImpl.java | 6 + ...hedAtUnqualifiedNoParenthesesCallImpl.java | 11 + .../psi/impl/ElixirMatchedDotCallImpl.java | 11 + ...irMatchedQualifiedNoArgumentsCallImpl.java | 11 + ...MatchedQualifiedNoParenthesesCallImpl.java | 11 + ...irMatchedQualifiedParenthesesCallImpl.java | 11 + ...MatchedUnqualifiedNoArgumentsCallImpl.java | 11 + ...tchedUnqualifiedNoParenthesesCallImpl.java | 11 + ...MatchedUnqualifiedParenthesesCallImpl.java | 11 + .../ElixirNoParenthesesManyArgumentsImpl.java | 6 + ...sitionalAndMaybeKeywordsArgumentsImpl.java | 6 + .../ElixirNoParenthesesOneArgumentImpl.java | 5 + ...OnePositionalAndKeywordsArgumentsImpl.java | 6 + .../impl/ElixirNoParenthesesStrictImpl.java | 6 + .../impl/ElixirParenthesesArgumentsImpl.java | 6 + ...hedAtUnqualifiedNoParenthesesCallImpl.java | 11 + .../psi/impl/ElixirUnmatchedDotCallImpl.java | 11 + ...UnmatchedQualifiedNoArgumentsCallImpl.java | 11 + ...matchedQualifiedNoParenthesesCallImpl.java | 11 + ...UnmatchedQualifiedParenthesesCallImpl.java | 11 + ...matchedUnqualifiedNoArgumentsCallImpl.java | 11 + ...tchedUnqualifiedNoParenthesesCallImpl.java | 10 + ...matchedUnqualifiedParenthesesCallImpl.java | 11 + ...iedNoParenthesesManyArgumentsCallImpl.java | 11 + src/org/elixir_lang/Elixir.bnf | 108 ++- .../elixir_lang/ElixirColorSettingsPage.java | 3 +- .../elixir_lang/ElixirSyntaxHighlighter.java | 5 + .../annonator/ModuleAttribute.java | 906 +++++++++++++++++- src/org/elixir_lang/psi/Arguments.java | 13 + .../psi/AtUnqualifiedNoParenthesesCall.java | 6 +- src/org/elixir_lang/psi/DotCall.java | 13 + .../psi/QualifiedNoArgumentsCall.java | 3 +- .../psi/QualifiedNoParenthesesCall.java | 4 +- .../psi/QualifiedParenthesesCall.java | 4 +- .../psi/UnqualifiedNoArgumentsCall.java | 3 +- .../psi/UnqualifiedNoParenthesesCall.java | 9 +- .../psi/UnqualifiedParenthesesCall.java | 6 +- src/org/elixir_lang/psi/WhenOperation.java | 7 + src/org/elixir_lang/psi/call/Call.java | 23 +- .../psi/call/arguments/NoParentheses.java | 33 + .../arguments/NoParenthesesOneArgument.java | 14 + .../elixir_lang/psi/call/arguments/None.java | 31 + .../psi/call/arguments/Parentheses.java | 27 + .../psi/impl/ElixirPsiImplUtil.java | 190 +++- .../psi/qualification/Unqualified.java | 3 + 70 files changed, 1749 insertions(+), 71 deletions(-) create mode 100644 src/org/elixir_lang/psi/Arguments.java create mode 100644 src/org/elixir_lang/psi/WhenOperation.java create mode 100644 src/org/elixir_lang/psi/call/arguments/NoParentheses.java create mode 100644 src/org/elixir_lang/psi/call/arguments/NoParenthesesOneArgument.java create mode 100644 src/org/elixir_lang/psi/call/arguments/None.java create mode 100644 src/org/elixir_lang/psi/call/arguments/Parentheses.java diff --git a/gen/org/elixir_lang/psi/ElixirMapConstructionArguments.java b/gen/org/elixir_lang/psi/ElixirMapConstructionArguments.java index 9a264f9ad..c597c263c 100644 --- a/gen/org/elixir_lang/psi/ElixirMapConstructionArguments.java +++ b/gen/org/elixir_lang/psi/ElixirMapConstructionArguments.java @@ -2,6 +2,7 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,6 +17,9 @@ public interface ElixirMapConstructionArguments extends QuotableArguments { @Nullable ElixirKeywords getKeywords(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirMatchedAtUnqualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirMatchedAtUnqualifiedNoParenthesesCall.java index 5026ed050..df9354722 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedAtUnqualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedAtUnqualifiedNoParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,6 +27,9 @@ public interface ElixirMatchedAtUnqualifiedNoParenthesesCall extends ElixirMatch @Nullable String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -35,4 +39,7 @@ public interface ElixirMatchedAtUnqualifiedNoParenthesesCall extends ElixirMatch @Nullable String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedDotCall.java b/gen/org/elixir_lang/psi/ElixirMatchedDotCall.java index cfec7fae6..e181c0050 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedDotCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedDotCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,9 @@ public interface ElixirMatchedDotCall extends ElixirMatchedExpression, DotCall, @Nullable String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -40,4 +44,7 @@ public interface ElixirMatchedDotCall extends ElixirMatchedExpression, DotCall, @Nullable String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoArgumentsCall.java b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoArgumentsCall.java index 774d652ed..36fd40b5b 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoArgumentsCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoArgumentsCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,9 @@ public interface ElixirMatchedQualifiedNoArgumentsCall extends ElixirMatchedExpr @Nullable ElixirDoBlock getDoBlock(); + @Nullable + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -37,4 +41,7 @@ public interface ElixirMatchedQualifiedNoArgumentsCall extends ElixirMatchedExpr @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoParenthesesCall.java index fc9c150be..8a3126ecc 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedNoParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,6 +21,9 @@ public interface ElixirMatchedQualifiedNoParenthesesCall extends ElixirMatchedEx @NotNull ElixirRelativeIdentifier getRelativeIdentifier(); + @NotNull + PsiElement[] primaryArguments(); + @Nullable String functionName(); @@ -40,4 +44,7 @@ public interface ElixirMatchedQualifiedNoParenthesesCall extends ElixirMatchedEx @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedParenthesesCall.java index 964953280..099a0824d 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedQualifiedParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedQualifiedParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,9 @@ public interface ElixirMatchedQualifiedParenthesesCall extends ElixirMatchedExpr @NotNull String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -40,4 +44,7 @@ public interface ElixirMatchedQualifiedParenthesesCall extends ElixirMatchedExpr @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoArgumentsCall.java b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoArgumentsCall.java index c80593a13..0044a3888 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoArgumentsCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoArgumentsCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,6 +21,9 @@ public interface ElixirMatchedUnqualifiedNoArgumentsCall extends ElixirMatchedEx @Nullable ElixirDoBlock getDoBlock(); + @Nullable + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -29,4 +33,7 @@ public interface ElixirMatchedUnqualifiedNoArgumentsCall extends ElixirMatchedEx @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoParenthesesCall.java index 139459a5f..2ebb82920 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedNoParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +24,9 @@ public interface ElixirMatchedUnqualifiedNoParenthesesCall extends ElixirMatched @Nullable ElixirDoBlock getDoBlock(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -32,4 +36,7 @@ public interface ElixirMatchedUnqualifiedNoParenthesesCall extends ElixirMatched @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedParenthesesCall.java index 50a1884ad..018c2f2f9 100644 --- a/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirMatchedUnqualifiedParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +24,9 @@ public interface ElixirMatchedUnqualifiedParenthesesCall extends ElixirMatchedEx @Nullable ElixirDoBlock getDoBlock(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -32,4 +36,7 @@ public interface ElixirMatchedUnqualifiedParenthesesCall extends ElixirMatchedEx @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirNoParenthesesManyArguments.java b/gen/org/elixir_lang/psi/ElixirNoParenthesesManyArguments.java index c432fa73e..0664c5c84 100644 --- a/gen/org/elixir_lang/psi/ElixirNoParenthesesManyArguments.java +++ b/gen/org/elixir_lang/psi/ElixirNoParenthesesManyArguments.java @@ -2,10 +2,11 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface ElixirNoParenthesesManyArguments extends QuotableArguments { +public interface ElixirNoParenthesesManyArguments extends Arguments, QuotableArguments { @Nullable ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments getNoParenthesesManyPositionalAndMaybeKeywordsArguments(); @@ -13,6 +14,9 @@ public interface ElixirNoParenthesesManyArguments extends QuotableArguments { @Nullable ElixirNoParenthesesOnePositionalAndKeywordsArguments getNoParenthesesOnePositionalAndKeywordsArguments(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments.java b/gen/org/elixir_lang/psi/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments.java index 2569911e0..36577134c 100644 --- a/gen/org/elixir_lang/psi/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments.java +++ b/gen/org/elixir_lang/psi/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments.java @@ -2,12 +2,13 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -public interface ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments extends QuotableArguments { +public interface ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments extends Arguments, QuotableArguments { @NotNull ElixirMatchedExpression getMatchedExpression(); @@ -18,6 +19,9 @@ public interface ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments exte @Nullable ElixirNoParenthesesKeywords getNoParenthesesKeywords(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirNoParenthesesOneArgument.java b/gen/org/elixir_lang/psi/ElixirNoParenthesesOneArgument.java index 583926185..315d3fe3e 100644 --- a/gen/org/elixir_lang/psi/ElixirNoParenthesesOneArgument.java +++ b/gen/org/elixir_lang/psi/ElixirNoParenthesesOneArgument.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface ElixirNoParenthesesOneArgument extends MaybeModuleName, QuotableArguments { +public interface ElixirNoParenthesesOneArgument extends Arguments, MaybeModuleName, QuotableArguments { @Nullable ElixirMatchedExpression getMatchedExpression(); @@ -25,6 +25,9 @@ public interface ElixirNoParenthesesOneArgument extends MaybeModuleName, Quotabl @Nullable ElixirUnqualifiedNoParenthesesManyArgumentsCall getUnqualifiedNoParenthesesManyArgumentsCall(); + @NotNull + PsiElement[] arguments(); + boolean isModuleName(); boolean processDeclarations(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, PsiElement place); diff --git a/gen/org/elixir_lang/psi/ElixirNoParenthesesOnePositionalAndKeywordsArguments.java b/gen/org/elixir_lang/psi/ElixirNoParenthesesOnePositionalAndKeywordsArguments.java index a224d7570..a779a3995 100644 --- a/gen/org/elixir_lang/psi/ElixirNoParenthesesOnePositionalAndKeywordsArguments.java +++ b/gen/org/elixir_lang/psi/ElixirNoParenthesesOnePositionalAndKeywordsArguments.java @@ -2,9 +2,10 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -public interface ElixirNoParenthesesOnePositionalAndKeywordsArguments extends QuotableArguments { +public interface ElixirNoParenthesesOnePositionalAndKeywordsArguments extends Arguments, QuotableArguments { @NotNull ElixirNoParenthesesFirstPositional getNoParenthesesFirstPositional(); @@ -12,6 +13,9 @@ public interface ElixirNoParenthesesOnePositionalAndKeywordsArguments extends Qu @NotNull ElixirNoParenthesesKeywords getNoParenthesesKeywords(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirNoParenthesesStrict.java b/gen/org/elixir_lang/psi/ElixirNoParenthesesStrict.java index 859c4f132..d924401e1 100644 --- a/gen/org/elixir_lang/psi/ElixirNoParenthesesStrict.java +++ b/gen/org/elixir_lang/psi/ElixirNoParenthesesStrict.java @@ -2,10 +2,11 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface ElixirNoParenthesesStrict extends QuotableArguments { +public interface ElixirNoParenthesesStrict extends Arguments, QuotableArguments { @Nullable ElixirEmptyParentheses getEmptyParentheses(); @@ -16,6 +17,9 @@ public interface ElixirNoParenthesesStrict extends QuotableArguments { @Nullable ElixirNoParenthesesManyArguments getNoParenthesesManyArguments(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirParenthesesArguments.java b/gen/org/elixir_lang/psi/ElixirParenthesesArguments.java index 817f40e36..865544864 100644 --- a/gen/org/elixir_lang/psi/ElixirParenthesesArguments.java +++ b/gen/org/elixir_lang/psi/ElixirParenthesesArguments.java @@ -2,12 +2,13 @@ package org.elixir_lang.psi; import com.ericsson.otp.erlang.OtpErlangObject; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -public interface ElixirParenthesesArguments extends QuotableArguments { +public interface ElixirParenthesesArguments extends Arguments, QuotableArguments { @NotNull List getEmptyParenthesesList(); @@ -21,6 +22,9 @@ public interface ElixirParenthesesArguments extends QuotableArguments { @Nullable ElixirUnqualifiedNoParenthesesManyArgumentsCall getUnqualifiedNoParenthesesManyArgumentsCall(); + @NotNull + PsiElement[] arguments(); + @NotNull OtpErlangObject[] quoteArguments(); diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedAtUnqualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedAtUnqualifiedNoParenthesesCall.java index 431c7efd4..3cf8b7d45 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedAtUnqualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedAtUnqualifiedNoParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,6 +27,9 @@ public interface ElixirUnmatchedAtUnqualifiedNoParenthesesCall extends ElixirUnm @Nullable String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -35,4 +39,7 @@ public interface ElixirUnmatchedAtUnqualifiedNoParenthesesCall extends ElixirUnm @Nullable String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedDotCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedDotCall.java index 337739024..88fd61605 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedDotCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedDotCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,9 @@ public interface ElixirUnmatchedDotCall extends ElixirUnmatchedExpression, DotCa @Nullable String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -40,4 +44,7 @@ public interface ElixirUnmatchedDotCall extends ElixirUnmatchedExpression, DotCa @Nullable String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoArgumentsCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoArgumentsCall.java index 1c117a579..3238367f8 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoArgumentsCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoArgumentsCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,9 @@ public interface ElixirUnmatchedQualifiedNoArgumentsCall extends ElixirUnmatched @NotNull String moduleName(); + @Nullable + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -37,4 +41,7 @@ public interface ElixirUnmatchedQualifiedNoArgumentsCall extends ElixirUnmatched @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoParenthesesCall.java index d22b7690c..311bd7209 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedNoParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,9 @@ public interface ElixirUnmatchedQualifiedNoParenthesesCall extends ElixirUnmatch @NotNull String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -40,4 +44,7 @@ public interface ElixirUnmatchedQualifiedNoParenthesesCall extends ElixirUnmatch @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedParenthesesCall.java index 40b3adbe2..6c1a7ed8a 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedQualifiedParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,9 @@ public interface ElixirUnmatchedQualifiedParenthesesCall extends ElixirUnmatched @NotNull String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -40,4 +44,7 @@ public interface ElixirUnmatchedQualifiedParenthesesCall extends ElixirUnmatched @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoArgumentsCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoArgumentsCall.java index a95d2562d..4de3fe3ba 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoArgumentsCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoArgumentsCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,6 +21,9 @@ public interface ElixirUnmatchedUnqualifiedNoArgumentsCall extends ElixirUnmatch @Nullable String moduleName(); + @Nullable + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -29,4 +33,7 @@ public interface ElixirUnmatchedUnqualifiedNoArgumentsCall extends ElixirUnmatch @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoParenthesesCall.java index 8ed39ebba..9f8e5bbf5 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedNoParenthesesCall.java @@ -28,6 +28,9 @@ public interface ElixirUnmatchedUnqualifiedNoParenthesesCall extends ElixirUnmat boolean isDefmodule(); + @NotNull + PsiElement[] primaryArguments(); + boolean processDeclarations(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, PsiElement place); @NotNull @@ -39,4 +42,7 @@ public interface ElixirUnmatchedUnqualifiedNoParenthesesCall extends ElixirUnmat @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedParenthesesCall.java b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedParenthesesCall.java index d925fdb92..b467e0a17 100644 --- a/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedParenthesesCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnmatchedUnqualifiedParenthesesCall.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +24,9 @@ public interface ElixirUnmatchedUnqualifiedParenthesesCall extends ElixirUnmatch @Nullable String moduleName(); + @NotNull + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -32,4 +36,7 @@ public interface ElixirUnmatchedUnqualifiedParenthesesCall extends ElixirUnmatch @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirUnqualifiedNoParenthesesManyArgumentsCall.java b/gen/org/elixir_lang/psi/ElixirUnqualifiedNoParenthesesManyArgumentsCall.java index 2f7bf2790..7d7f27623 100644 --- a/gen/org/elixir_lang/psi/ElixirUnqualifiedNoParenthesesManyArgumentsCall.java +++ b/gen/org/elixir_lang/psi/ElixirUnqualifiedNoParenthesesManyArgumentsCall.java @@ -5,11 +5,12 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.NoParentheses; import org.elixir_lang.psi.qualification.Unqualified; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface ElixirUnqualifiedNoParenthesesManyArgumentsCall extends PsiElement, Call, Unqualified, Quotable, QuotableArguments { +public interface ElixirUnqualifiedNoParenthesesManyArgumentsCall extends PsiElement, Call, NoParentheses, Unqualified, Quotable, QuotableArguments { @Nullable ElixirNoParenthesesManyArguments getNoParenthesesManyArguments(); @@ -38,6 +39,9 @@ public interface ElixirUnqualifiedNoParenthesesManyArgumentsCall extends PsiElem @NotNull Quotable getIdentifier(); + @Nullable + PsiElement[] primaryArguments(); + @NotNull OtpErlangObject quote(); @@ -52,4 +56,7 @@ public interface ElixirUnqualifiedNoParenthesesManyArgumentsCall extends PsiElem @NotNull String resolvedModuleName(); + @Nullable + PsiElement[] secondaryArguments(); + } diff --git a/gen/org/elixir_lang/psi/ElixirVisitor.java b/gen/org/elixir_lang/psi/ElixirVisitor.java index 15c0e484b..bdfac26b5 100644 --- a/gen/org/elixir_lang/psi/ElixirVisitor.java +++ b/gen/org/elixir_lang/psi/ElixirVisitor.java @@ -629,7 +629,8 @@ public void visitNoParenthesesKeywords(@NotNull ElixirNoParenthesesKeywords o) { } public void visitNoParenthesesManyArguments(@NotNull ElixirNoParenthesesManyArguments o) { - visitQuotableArguments(o); + visitArguments(o); + // visitQuotableArguments(o); } public void visitNoParenthesesManyArgumentsUnqualifiedIdentifier(@NotNull ElixirNoParenthesesManyArgumentsUnqualifiedIdentifier o) { @@ -637,7 +638,8 @@ public void visitNoParenthesesManyArgumentsUnqualifiedIdentifier(@NotNull Elixir } public void visitNoParenthesesManyPositionalAndMaybeKeywordsArguments(@NotNull ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments o) { - visitQuotableArguments(o); + visitArguments(o); + // visitQuotableArguments(o); } public void visitNoParenthesesManyStrictNoParenthesesExpression(@NotNull ElixirNoParenthesesManyStrictNoParenthesesExpression o) { @@ -645,16 +647,19 @@ public void visitNoParenthesesManyStrictNoParenthesesExpression(@NotNull ElixirN } public void visitNoParenthesesOneArgument(@NotNull ElixirNoParenthesesOneArgument o) { - visitMaybeModuleName(o); + visitArguments(o); + // visitMaybeModuleName(o); // visitQuotableArguments(o); } public void visitNoParenthesesOnePositionalAndKeywordsArguments(@NotNull ElixirNoParenthesesOnePositionalAndKeywordsArguments o) { - visitQuotableArguments(o); + visitArguments(o); + // visitQuotableArguments(o); } public void visitNoParenthesesStrict(@NotNull ElixirNoParenthesesStrict o) { - visitQuotableArguments(o); + visitArguments(o); + // visitQuotableArguments(o); } public void visitOctalDigits(@NotNull ElixirOctalDigits o) { @@ -674,7 +679,8 @@ public void visitOrInfixOperator(@NotNull ElixirOrInfixOperator o) { } public void visitParenthesesArguments(@NotNull ElixirParenthesesArguments o) { - visitQuotableArguments(o); + visitArguments(o); + // visitQuotableArguments(o); } public void visitParentheticalStab(@NotNull ElixirParentheticalStab o) { @@ -942,6 +948,7 @@ public void visitUnmatchedWhenOperation(@NotNull ElixirUnmatchedWhenOperation o) public void visitUnqualifiedNoParenthesesManyArgumentsCall(@NotNull ElixirUnqualifiedNoParenthesesManyArgumentsCall o) { visitPsiElement(o); // visitCall(o); + // visitNoParentheses(o); // visitUnqualified(o); // visitQuotable(o); // visitQuotableArguments(o); @@ -955,6 +962,10 @@ public void visitWhenInfixOperator(@NotNull ElixirWhenInfixOperator o) { visitOperator(o); } + public void visitArguments(@NotNull Arguments o) { + visitElement(o); + } + public void visitAssociationOperation(@NotNull AssociationOperation o) { visitElement(o); } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMapConstructionArgumentsImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMapConstructionArgumentsImpl.java index e46adb7df..d43b43e6b 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMapConstructionArgumentsImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMapConstructionArgumentsImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -38,6 +39,11 @@ public ElixirKeywords getKeywords() { return findChildByClass(ElixirKeywords.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedAtUnqualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedAtUnqualifiedNoParenthesesCallImpl.java index a59e67dd3..c542684b3 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedAtUnqualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedAtUnqualifiedNoParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -51,6 +52,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -66,4 +72,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedDotCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedDotCallImpl.java index 1051f4cb4..9dfd614ea 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedDotCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedDotCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import org.elixir_lang.psi.*; @@ -60,6 +61,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -75,4 +81,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoArgumentsCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoArgumentsCallImpl.java index c37662969..d1a1a402c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoArgumentsCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoArgumentsCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -56,6 +57,11 @@ public ElixirDoBlock getDoBlock() { return ElixirPsiImplUtil.getDoBlock(this); } + @Nullable + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -71,4 +77,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoParenthesesCallImpl.java index 3479131ae..2384305b5 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedNoParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -43,6 +44,11 @@ public ElixirRelativeIdentifier getRelativeIdentifier() { return findNotNullChildByClass(ElixirRelativeIdentifier.class); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @Nullable public String functionName() { return ElixirPsiImplUtil.functionName(this); @@ -77,4 +83,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedParenthesesCallImpl.java index df47139ea..2406f7636 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedQualifiedParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -62,6 +63,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -77,4 +83,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoArgumentsCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoArgumentsCallImpl.java index 83c9bfbeb..8469ab1a2 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoArgumentsCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoArgumentsCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirDoBlock; import org.elixir_lang.psi.ElixirMatchedUnqualifiedNoArgumentsCall; @@ -41,6 +42,11 @@ public ElixirDoBlock getDoBlock() { return ElixirPsiImplUtil.getDoBlock(this); } + @Nullable + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -56,4 +62,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoParenthesesCallImpl.java index 4775ab7e4..a8262d158 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedNoParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirDoBlock; import org.elixir_lang.psi.ElixirMatchedUnqualifiedNoParenthesesCall; @@ -48,6 +49,11 @@ public ElixirDoBlock getDoBlock() { return ElixirPsiImplUtil.getDoBlock(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -63,4 +69,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedParenthesesCallImpl.java index e6f21d82a..1b4db1f50 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirMatchedUnqualifiedParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirDoBlock; import org.elixir_lang.psi.ElixirMatchedParenthesesArguments; @@ -48,6 +49,11 @@ public ElixirDoBlock getDoBlock() { return ElixirPsiImplUtil.getDoBlock(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -63,4 +69,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyArgumentsImpl.java b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyArgumentsImpl.java index 8c42c50a1..680857519 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyArgumentsImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyArgumentsImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirNoParenthesesManyArguments; import org.elixir_lang.psi.ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments; @@ -35,6 +36,11 @@ public ElixirNoParenthesesOnePositionalAndKeywordsArguments getNoParenthesesOneP return findChildByClass(ElixirNoParenthesesOnePositionalAndKeywordsArguments.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArgumentsImpl.java b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArgumentsImpl.java index 3e74800ff..6f057dd01 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArgumentsImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesManyPositionalAndMaybeKeywordsArgumentsImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import org.elixir_lang.psi.*; @@ -41,6 +42,11 @@ public ElixirNoParenthesesKeywords getNoParenthesesKeywords() { return findChildByClass(ElixirNoParenthesesKeywords.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOneArgumentImpl.java b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOneArgumentImpl.java index 3930739a7..142bb1828 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOneArgumentImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOneArgumentImpl.java @@ -53,6 +53,11 @@ public ElixirUnqualifiedNoParenthesesManyArgumentsCall getUnqualifiedNoParenthes return findChildByClass(ElixirUnqualifiedNoParenthesesManyArgumentsCall.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + public boolean isModuleName() { return ElixirPsiImplUtil.isModuleName(this); } diff --git a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOnePositionalAndKeywordsArgumentsImpl.java b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOnePositionalAndKeywordsArgumentsImpl.java index 604586f7c..8f230c6ca 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOnePositionalAndKeywordsArgumentsImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesOnePositionalAndKeywordsArgumentsImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirNoParenthesesFirstPositional; import org.elixir_lang.psi.ElixirNoParenthesesKeywords; @@ -34,6 +35,11 @@ public ElixirNoParenthesesKeywords getNoParenthesesKeywords() { return findNotNullChildByClass(ElixirNoParenthesesKeywords.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesStrictImpl.java b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesStrictImpl.java index dc9a60366..3ec0c0048 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesStrictImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirNoParenthesesStrictImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -38,6 +39,11 @@ public ElixirNoParenthesesManyArguments getNoParenthesesManyArguments() { return findChildByClass(ElixirNoParenthesesManyArguments.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirParenthesesArgumentsImpl.java b/gen/org/elixir_lang/psi/impl/ElixirParenthesesArgumentsImpl.java index 0973a72a5..6b5ad16fb 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirParenthesesArgumentsImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirParenthesesArgumentsImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import org.elixir_lang.psi.*; @@ -47,6 +48,11 @@ public ElixirUnqualifiedNoParenthesesManyArgumentsCall getUnqualifiedNoParenthes return findChildByClass(ElixirUnqualifiedNoParenthesesManyArgumentsCall.class); } + @NotNull + public PsiElement[] arguments() { + return ElixirPsiImplUtil.arguments(this); + } + @NotNull public OtpErlangObject[] quoteArguments() { return ElixirPsiImplUtil.quoteArguments(this); diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAtUnqualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAtUnqualifiedNoParenthesesCallImpl.java index bd00ced48..f642e126c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAtUnqualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedAtUnqualifiedNoParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -52,6 +53,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -67,4 +73,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedDotCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedDotCallImpl.java index 8325bb954..6f237a54e 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedDotCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedDotCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import org.elixir_lang.psi.*; @@ -61,6 +62,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -76,4 +82,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoArgumentsCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoArgumentsCallImpl.java index 26ca26845..c5c29c412 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoArgumentsCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoArgumentsCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -57,6 +58,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @Nullable + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -72,4 +78,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoParenthesesCallImpl.java index cdcc995e4..585e22348 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedNoParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -63,6 +64,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -78,4 +84,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedParenthesesCallImpl.java index 35bf9bb0a..279185034 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedQualifiedParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -63,6 +64,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -78,4 +84,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoArgumentsCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoArgumentsCallImpl.java index b9f84bb14..830b87ceb 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoArgumentsCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoArgumentsCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirDoBlock; import org.elixir_lang.psi.ElixirUnmatchedUnqualifiedNoArgumentsCall; @@ -42,6 +43,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @Nullable + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -57,4 +63,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.java index ca1d961db..3c269d109 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.java @@ -56,6 +56,11 @@ public boolean isDefmodule() { return ElixirPsiImplUtil.isDefmodule(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + public boolean processDeclarations(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, PsiElement place) { return ElixirPsiImplUtil.processDeclarations(this, processor, state, lastParent, place); } @@ -75,4 +80,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedParenthesesCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedParenthesesCallImpl.java index a711fbe50..5f8af4dcb 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedParenthesesCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnmatchedUnqualifiedParenthesesCallImpl.java @@ -3,6 +3,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.ElixirDoBlock; import org.elixir_lang.psi.ElixirMatchedParenthesesArguments; @@ -49,6 +50,11 @@ public String moduleName() { return ElixirPsiImplUtil.moduleName(this); } + @NotNull + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -64,4 +70,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/gen/org/elixir_lang/psi/impl/ElixirUnqualifiedNoParenthesesManyArgumentsCallImpl.java b/gen/org/elixir_lang/psi/impl/ElixirUnqualifiedNoParenthesesManyArgumentsCallImpl.java index 390f916fe..05ca55f9c 100644 --- a/gen/org/elixir_lang/psi/impl/ElixirUnqualifiedNoParenthesesManyArgumentsCallImpl.java +++ b/gen/org/elixir_lang/psi/impl/ElixirUnqualifiedNoParenthesesManyArgumentsCallImpl.java @@ -4,6 +4,7 @@ import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import org.elixir_lang.psi.*; import org.jetbrains.annotations.NotNull; @@ -68,6 +69,11 @@ public Quotable getIdentifier() { return ElixirPsiImplUtil.getIdentifier(this); } + @Nullable + public PsiElement[] primaryArguments() { + return ElixirPsiImplUtil.primaryArguments(this); + } + @NotNull public OtpErlangObject quote() { return ElixirPsiImplUtil.quote(this); @@ -92,4 +98,9 @@ public String resolvedModuleName() { return ElixirPsiImplUtil.resolvedModuleName(this); } + @Nullable + public PsiElement[] secondaryArguments() { + return ElixirPsiImplUtil.secondaryArguments(this); + } + } diff --git a/src/org/elixir_lang/Elixir.bnf b/src/org/elixir_lang/Elixir.bnf index 69ff36fc5..c290ec3e4 100644 --- a/src/org/elixir_lang/Elixir.bnf +++ b/src/org/elixir_lang/Elixir.bnf @@ -222,21 +222,57 @@ noParenthesesStrict ::= emptyParentheses | noParenthesesKeywords | noParenthesesManyArguments ) CLOSING_PARENTHESIS - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = [ + "org.elixir_lang.psi.Arguments" + "org.elixir_lang.psi.QuotableArguments" + ] + methods = [ + arguments + quoteArguments + ] + } noParenthesesFirstPositional ::= matchedExpression { implements = "org.elixir_lang.psi.Quotable" methods = [quote] } noParenthesesOnePositionalAndKeywordsArguments ::= noParenthesesFirstPositional infixComma noParenthesesKeywords - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = [ + "org.elixir_lang.psi.Arguments" + "org.elixir_lang.psi.QuotableArguments" + ] + methods = [ + arguments + quoteArguments + ] + } noParenthesesManyPositionalAndMaybeKeywordsArguments ::= noParenthesesCommaExpression (infixComma noParenthesesKeywords)? - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = [ + "org.elixir_lang.psi.Arguments" + "org.elixir_lang.psi.QuotableArguments" + ] + methods = [ + arguments + quoteArguments + ] + } /* 1. (positional, keywords) 2. (positional, positional) 3. (positional, positional, keywords) */ noParenthesesManyArguments ::= noParenthesesOnePositionalAndKeywordsArguments | noParenthesesManyPositionalAndMaybeKeywordsArguments - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = [ + "org.elixir_lang.psi.Arguments" + "org.elixir_lang.psi.QuotableArguments" + ] + methods = [ + arguments + quoteArguments + ] + } private noParenthesesManyArgumentsStrict ::= noParenthesesManyArguments | noParenthesesStrict @@ -251,6 +287,7 @@ unqualifiedNoParenthesesManyArgumentsCall ::= noParenthesesManyArgumentsUnqualif // MUST be first so visitElement is used in ElixirVisitor "com.intellij.psi.PsiElement" "org.elixir_lang.psi.call.Call" + "org.elixir_lang.psi.call.arguments.NoParentheses" "org.elixir_lang.psi.qualification.Unqualified" "org.elixir_lang.psi.Quotable" "org.elixir_lang.psi.QuotableArguments" @@ -262,11 +299,13 @@ unqualifiedNoParenthesesManyArgumentsCall ::= noParenthesesManyArgumentsUnqualif getArguments getDoBlock getIdentifier + primaryArguments quote quoteArguments quoteIdentifier resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1577,7 +1616,16 @@ parenthesesArguments ::= OPENING_PARENTHESIS EOL* keywords | // @see https://github.com/elixir-lang/elixir/blob/39b6789a8625071e149f0a7347ca7a2111f7c8f2/lib/elixir/src/elixir_parser.yrl#L486 parenthesesPositionalArguments (infixComma keywords)?)? EOL* // @see https://github.com/elixir-lang/elixir/blob/39b6789a8625071e149f0a7347ca7a2111f7c8f2/lib/elixir/src/elixir_parser.yrl#L487-L488 CLOSING_PARENTHESIS - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = [ + "org.elixir_lang.psi.Arguments" + "org.elixir_lang.psi.QuotableArguments" + ] + methods = [ + arguments + quoteArguments + ] + } // call_args_no_parens_one noParenthesesOneArgument ::= noParenthesesKeywords | // @see https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L417 @@ -1599,10 +1647,12 @@ noParenthesesOneArgument ::= noParenthesesKeywords | // @see https://github.com/ !additionTail matchedExpression { implements = [ + "org.elixir_lang.psi.Arguments" "org.elixir_lang.psi.MaybeModuleName" "org.elixir_lang.psi.QuotableArguments" ] methods = [ + arguments isModuleName processDeclarations quoteArguments @@ -1641,9 +1691,11 @@ matchedDotCall ::= matchedExpression dotInfixOperator parenthesesArguments paren functionNameNode getDoBlock moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1660,6 +1712,7 @@ matchedQualifiedNoParenthesesCall ::= matchedExpression dotInfixOperator relativ "org.elixir_lang.psi.QualifiedNoParenthesesCall" ] methods = [ + primaryArguments functionName functionNameNode getDoBlock @@ -1667,6 +1720,7 @@ matchedQualifiedNoParenthesesCall ::= matchedExpression dotInfixOperator relativ quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1689,9 +1743,11 @@ matchedAtUnqualifiedNoParenthesesCall ::= atPrefixOperator IDENTIFIER noParenthe functionNameNode getDoBlock moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1712,9 +1768,11 @@ matchedUnqualifiedNoParenthesesCall ::= IDENTIFIER noParenthesesOneArgument functionNameNode moduleName getDoBlock + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1786,9 +1844,11 @@ matchedQualifiedParenthesesCall ::= matchedExpression dotInfixOperator relativeI functionNameNode getDoBlock moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1807,9 +1867,11 @@ matchedQualifiedNoArgumentsCall ::= matchedExpression dotInfixOperator relativeI functionNameNode moduleName getDoBlock + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -1839,9 +1901,11 @@ matchedUnqualifiedParenthesesCall ::= IDENTIFIER matchedParenthesesArguments functionNameNode moduleName getDoBlock + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } /* @@ -1890,9 +1954,11 @@ matchedUnqualifiedNoArgumentsCall ::= IDENTIFIER !KEYWORD_PAIR_COLON functionNameNode moduleName getDoBlock + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2030,7 +2096,13 @@ mapUpdateArguments ::= matchedMatchOperation pipeInfixOperator mapTailArguments { implements = "org.elixir_lang.psi.Quotable" methods = [quote] } mapConstructionArguments ::= mapTailArguments - { implements = "org.elixir_lang.psi.QuotableArguments" methods = [quoteArguments] } + { + implements = "org.elixir_lang.psi.QuotableArguments" + methods = [ + arguments + quoteArguments + ] + } mapArguments ::= OPENING_CURLY EOL* ( @@ -2071,7 +2143,13 @@ stabNoParenthesesSignature ::= noParenthesesArguments * @see https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L430-L432 */ stabParenthesesSignature ::= parenthesesArguments (whenInfixOperator expression)? - { implements = "org.elixir_lang.psi.Quotable" methods = [quote] } + { + implements = [ + "org.elixir_lang.psi.Quotable" + "org.elixir_lang.psi.WhenOperation" + ] + methods = [quote] + } stabInfixOperator ::= EOL* STAB_OPERATOR EOL* { @@ -2514,9 +2592,11 @@ unmatchedDotCall ::= unmatchedExpression dotInfixOperator parenthesesArguments p functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2533,9 +2613,11 @@ unmatchedQualifiedNoParenthesesCall ::= unmatchedExpression dotInfixOperator rel functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2554,9 +2636,11 @@ unmatchedAtUnqualifiedNoParenthesesCall ::= atPrefixOperator IDENTIFIER noParent functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2574,10 +2658,12 @@ unmatchedUnqualifiedNoParenthesesCall ::= IDENTIFIER noParenthesesOneArgument do functionNameNode moduleName isDefmodule + primaryArguments processDeclarations quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2630,9 +2716,11 @@ unmatchedQualifiedParenthesesCall ::= unmatchedExpression dotInfixOperator relat functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2647,9 +2735,11 @@ unmatchedQualifiedNoArgumentsCall ::= unmatchedExpression dotInfixOperator relat functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2675,9 +2765,11 @@ unmatchedUnqualifiedParenthesesCall ::= IDENTIFIER matchedParenthesesArguments d functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } @@ -2713,9 +2805,11 @@ unmatchedUnqualifiedNoArgumentsCall ::= IDENTIFIER !KEYWORD_PAIR_COLON doBlock? functionName functionNameNode moduleName + primaryArguments quote resolvedFunctionName resolvedModuleName + secondaryArguments ] } diff --git a/src/org/elixir_lang/ElixirColorSettingsPage.java b/src/org/elixir_lang/ElixirColorSettingsPage.java index 5d9d0d36c..7f7b0aa2f 100644 --- a/src/org/elixir_lang/ElixirColorSettingsPage.java +++ b/src/org/elixir_lang/ElixirColorSettingsPage.java @@ -45,7 +45,8 @@ public class ElixirColorSettingsPage implements ColorSettingsPage { new AttributesDescriptor("Sigil", ElixirSyntaxHighlighter.SIGIL), new AttributesDescriptor("Specification", ElixirSyntaxHighlighter.SPECIFICATION), new AttributesDescriptor("String", ElixirSyntaxHighlighter.STRING), - new AttributesDescriptor("Type", ElixirSyntaxHighlighter.TYPE) + new AttributesDescriptor("Type", ElixirSyntaxHighlighter.TYPE), + new AttributesDescriptor("Type Parameter", ElixirSyntaxHighlighter.TYPE_PARAMETER) }; @Nullable diff --git a/src/org/elixir_lang/ElixirSyntaxHighlighter.java b/src/org/elixir_lang/ElixirSyntaxHighlighter.java index ecae87b34..45e0376fc 100644 --- a/src/org/elixir_lang/ElixirSyntaxHighlighter.java +++ b/src/org/elixir_lang/ElixirSyntaxHighlighter.java @@ -144,6 +144,11 @@ public class ElixirSyntaxHighlighter extends SyntaxHighlighterBase { CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES ); + public static final TextAttributesKey TYPE_PARAMETER = createTextAttributesKey( + "ELIXIR_TYPE_PARAMETER", + CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES + ); + public static final TextAttributesKey VALID_DIGIT = createTextAttributesKey( "ELIXIR_VALID_DIGIT", DefaultLanguageHighlighterColors.NUMBER diff --git a/src/org/elixir_lang/annonator/ModuleAttribute.java b/src/org/elixir_lang/annonator/ModuleAttribute.java index 95f3de400..6867296f2 100644 --- a/src/org/elixir_lang/annonator/ModuleAttribute.java +++ b/src/org/elixir_lang/annonator/ModuleAttribute.java @@ -3,7 +3,6 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; -import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; @@ -12,13 +11,18 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiRecursiveElementVisitor; import com.intellij.psi.tree.TokenSet; +import org.apache.commons.lang.NotImplementedException; import org.elixir_lang.ElixirSyntaxHighlighter; import org.elixir_lang.psi.*; import org.elixir_lang.psi.call.Call; import org.elixir_lang.psi.impl.ElixirPsiImplUtil; import org.jetbrains.annotations.NotNull; +import java.awt.font.TextAttribute; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Annotates module attributes. @@ -99,8 +103,8 @@ public void visitElement(@NotNull final PsiElement element) { /** * Highlights `textRange` with the given `textAttributesKey`. * - * @param textRange textRange in the document to highlight - * @param annotationHolder the container which receives annotations created by the plugin. + * @param textRange textRange in the document to highlight + * @param annotationHolder the container which receives annotations created by the plugin. * @param textAttributesKey text attributes to apply to the `node`. */ private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHolder annotationHolder, @NotNull final TextAttributesKey textAttributesKey) { @@ -110,7 +114,12 @@ private void highlight(@NotNull final TextRange textRange, @NotNull AnnotationHo private void highlightCallback(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, @NotNull final AnnotationHolder annotationHolder) { - highlightSpecification(atUnqualifiedNoParenthesesCall, annotationHolder, ElixirSyntaxHighlighter.CALLBACK); + highlightSpecification( + atUnqualifiedNoParenthesesCall, + annotationHolder, + ElixirSyntaxHighlighter.CALLBACK, + ElixirSyntaxHighlighter.TYPE + ); } private void highlightDocumentationText( @@ -169,9 +178,9 @@ private void highlightDocumentationText( /** * Highlights fragment ASTNodes under `body` that have fragment type from `fragmented.getFragmentType()`. * - * @param fragmented supplies fragment type - * @param body contains fragments - * @param annotationHolder the container which receives annotations created by the plugin. + * @param fragmented supplies fragment type + * @param body contains fragments + * @param annotationHolder the container which receives annotations created by the plugin. * @param textAttributesKey text attributes to apply to the fragments. */ private void highlightFragments(@NotNull final Fragmented fragmented, @@ -200,44 +209,209 @@ private void highlightFragments(@NotNull final Fragmented fragmented, */ private void highlightSpecification(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, @NotNull final AnnotationHolder annotationHolder) { - highlightSpecification(atUnqualifiedNoParenthesesCall, annotationHolder, ElixirSyntaxHighlighter.SPECIFICATION); + highlightSpecification( + atUnqualifiedNoParenthesesCall, + annotationHolder, + ElixirSyntaxHighlighter.SPECIFICATION, + ElixirSyntaxHighlighter.TYPE + ); } /** - * Highlight the function call name using the given `textAttributesKey` - * - * @param atUnqualifiedNoParenthesesCall - * @param annotationHolder - * @param textAttributesKey + * Highlights the function name of the declared @type, @typep, or @opaque as an {@link ElixirSyntaxHighlighter.TYPE} + * and the its parameters as {@link ElixirSyntaxHighlighter.TYPE_PARAMETER}. */ - private void highlightSpecification(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, - @NotNull final AnnotationHolder annotationHolder, - @NotNull final TextAttributesKey textAttributesKey) { + private void highlightType(@NotNull final AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + @NotNull final AnnotationHolder annotationHolder) { PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); if (grandChildren.length == 1) { PsiElement grandChild = grandChildren[0]; - if (grandChild instanceof ElixirMatchedTypeOperation) { + if (grandChild instanceof ElixirMatchedMatchOperation) { + // TODO LocalInspectionTool with quick fix to "Use `::`, not `=`, to separate types declarations from their definitions" + } else if (grandChild instanceof ElixirMatchedTypeOperation) { InfixOperation infixOperation = (InfixOperation) grandChild; PsiElement leftOperand = infixOperation.leftOperand(); + Set typeParameterNameSet = Collections.EMPTY_SET; if (leftOperand instanceof Call) { Call call = (Call) leftOperand; ASTNode functionNameNode = call.functionNameNode(); if (functionNameNode != null) { - highlight(functionNameNode.getTextRange(), annotationHolder, textAttributesKey); + highlight( + functionNameNode.getTextRange(), + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } + + if (call instanceof ElixirMatchedUnqualifiedNoArgumentsCall) { + // no arguments, so nothing else to do + } else if (call instanceof ElixirMatchedUnqualifiedParenthesesCall) { + PsiElement[] primaryArguments = call.primaryArguments(); + PsiElement[] secondaryArguments = call.secondaryArguments(); + + /* if there are secondaryArguments, then it is the type parameters as in + `@type quote(type_name)(param1, param2) :: {param1, param2}` */ + if (secondaryArguments != null) { + typeParameterNameSet = typeTypeParameterNameSet(secondaryArguments); + + highlightTypesAndTypeParameterUsages( + primaryArguments, + /* as stated above, if there are secondary arguments, then the primary arguments are + to quote or some equivalent metaprogramming. */ + Collections.EMPTY_SET, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + + highlightTypesAndTypeTypeParameterDeclarations( + secondaryArguments, + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } else if (primaryArguments != null) { + typeParameterNameSet = typeTypeParameterNameSet(primaryArguments); + + highlightTypesAndTypeTypeParameterDeclarations( + primaryArguments, + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } + } else { + throw new NotImplementedException( + "Highlighting types for " + call.getClass().getCanonicalName() + " PsiElements is " + + "not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class " + + "name of the sample text:\n" + ((PsiElement) call).getText() + ); } + } else { + throw new NotImplementedException( + "Highlighting types for " + leftOperand.getClass().getCanonicalName() + " PsiElements is " + + "not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name of " + + "the sample text:\n" + leftOperand.getText() + ); } + + PsiElement rightOperand = infixOperation.rightOperand(); + + highlightTypesAndTypeParameterUsages( + rightOperand, + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } else if (grandChild instanceof ElixirMatchedUnqualifiedParenthesesCall) { + // seen as `unquote(ast)`, but could also be just the beginning of typing + ElixirMatchedUnqualifiedParenthesesCall matchedUnqualifiedParenthesesCall = (ElixirMatchedUnqualifiedParenthesesCall) grandChild; + + if (matchedUnqualifiedParenthesesCall.functionName().equals("unquote")) { + PsiElement[] secondaryArguments = matchedUnqualifiedParenthesesCall.secondaryArguments(); + + if (secondaryArguments != null) { + Set typeParameterNameSet = typeTypeParameterNameSet(secondaryArguments); + + highlightTypesAndTypeTypeParameterDeclarations( + secondaryArguments, + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } + } else { + throw new NotImplementedException( + "Highlighting types for " + + matchedUnqualifiedParenthesesCall.getClass().getCanonicalName() + " PsiElements " + + "is not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name " + + "of the sample text:\n" + grandChild.getText() + ); + } + } else { + throw new NotImplementedException( + "Highlighting types for " + grandChild.getClass().getCanonicalName() + " PsiElements is not " + + "implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name of " + + "the sample text:\n" + grandChild.getText() + ); } } } + private void highlightTypesAndTypeTypeParameterDeclarations(ElixirUnmatchedUnqualifiedNoArgumentsCall psiElement, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + String name = psiElement.getText(); + TextAttributesKey textAttributesKey; + + if (typeParameterNameSet.contains(name)) { + textAttributesKey = ElixirSyntaxHighlighter.TYPE_PARAMETER; + } else { + textAttributesKey = typeTextAttributesKey; + } - private void highlightType(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, - AnnotationHolder annotationHolder) { + highlight(psiElement.getTextRange(), annotationHolder, textAttributesKey); + } + + private void highlightTypesAndTypeTypeParameterDeclarations(PsiElement psiElement, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + if (psiElement instanceof ElixirUnmatchedUnqualifiedNoArgumentsCall) { + highlightTypesAndTypeTypeParameterDeclarations( + (ElixirUnmatchedUnqualifiedNoArgumentsCall) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else { + throw new NotImplementedException( + "Highlighting types and type type parameter declarations for " + + psiElement.getClass().getCanonicalName() + " PsiElements is not implemented yet. Please " + + "open an issue (https://github.com/KronicDeth/intellij-elixir/issues/new) with the class " + + "name of the sample text:\n" + psiElement.getText() + ); + } + } + + private void highlightTypesAndTypeTypeParameterDeclarations( + PsiElement[] psiElements, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + for (PsiElement psiElement : psiElements) { + highlightTypesAndTypeTypeParameterDeclarations( + psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + } + + /** + * Recursively highlights the types under `atUnqualifiedNoParenthesesCall`. + * + * @param atUnqualifiedNoParenthesesCall + * @param annotationHolder + * @param leftMostFunctionNameTextAttributesKey the {@link ElixirSyntaxHighlighter} {@link TextAttributesKey} for the + * name of the callback, type, or function being declared + * @param leftMostFunctionArgumentsTextAttributesKey the {@link ElixirSyntaxHighlighter} {@link TextAttributesKey} for the + * arguments of the callback, type, or function being declared + */ + private void highlightSpecification(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall, + AnnotationHolder annotationHolder, + TextAttributesKey leftMostFunctionNameTextAttributesKey, + TextAttributesKey leftMostFunctionArgumentsTextAttributesKey) { PsiElement noParenthesesOneArgument = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument(); PsiElement[] grandChildren = noParenthesesOneArgument.getChildren(); @@ -253,10 +427,700 @@ private void highlightType(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenth ASTNode functionNameNode = call.functionNameNode(); if (functionNameNode != null) { - highlight(functionNameNode.getTextRange(), annotationHolder, ElixirSyntaxHighlighter.TYPE); + highlight( + functionNameNode.getTextRange(), + annotationHolder, + leftMostFunctionNameTextAttributesKey + ); + } + + PsiElement[] primaryArguments = call.primaryArguments(); + + if (primaryArguments != null) { + highlightTypesAndTypeParameterUsages( + primaryArguments, + Collections.EMPTY_SET, + annotationHolder, + leftMostFunctionArgumentsTextAttributesKey + ); + } + + PsiElement[] secondaryArguments = call.secondaryArguments(); + + if (secondaryArguments != null) { + highlightTypesAndTypeParameterUsages( + secondaryArguments, + Collections.EMPTY_SET, + annotationHolder, + leftMostFunctionArgumentsTextAttributesKey + ); + } + } + + PsiElement rightOperand = infixOperation.rightOperand(); + + highlightTypesAndTypeParameterUsages( + rightOperand, + Collections.EMPTY_SET, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } else if (grandChild instanceof ElixirMatchedWhenOperation) { + ElixirMatchedWhenOperation matchedWhenOperation = (ElixirMatchedWhenOperation) grandChild; + Set typeParameterNameSet = specificationTypeParameterNameSet(matchedWhenOperation.rightOperand()); + + PsiElement leftOperand = matchedWhenOperation.leftOperand(); + + if (leftOperand instanceof ElixirMatchedTypeOperation) { + ElixirMatchedTypeOperation matchedTypeOperation = (ElixirMatchedTypeOperation) leftOperand; + PsiElement matchedTypeOperationLeftOperand = matchedTypeOperation.leftOperand(); + + if (matchedTypeOperationLeftOperand instanceof Call) { + Call call = (Call) matchedTypeOperationLeftOperand; + ASTNode functionNameNode = call.functionNameNode(); + + if (functionNameNode != null) { + highlight( + functionNameNode.getTextRange(), + annotationHolder, + leftMostFunctionNameTextAttributesKey + ); + } + + PsiElement[] primaryArguments = call.primaryArguments(); + + if (primaryArguments != null) { + highlightTypesAndTypeParameterUsages( + primaryArguments, + typeParameterNameSet, + annotationHolder, + leftMostFunctionArgumentsTextAttributesKey + ); + } + + PsiElement[] secondaryArguments = call.secondaryArguments(); + + if (secondaryArguments != null) { + highlightTypesAndTypeParameterUsages( + secondaryArguments, + typeParameterNameSet, + annotationHolder, + leftMostFunctionArgumentsTextAttributesKey + ); + } + } else { + throw new NotImplementedException( + "Highlighting types for " + + matchedTypeOperationLeftOperand.getClass().getCanonicalName() + + " PsiElements that are the left operand of " + + matchedTypeOperation.getClass().getCanonicalName() + " is not implemented " + + "yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class " + + "name of the sample text:\n" + matchedWhenOperation.getText() + ); } + + PsiElement matchedTypeOperationRightOperand = matchedTypeOperation.rightOperand(); + + highlightTypesAndTypeParameterUsages( + matchedTypeOperationRightOperand, + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); + } else { + throw new NotImplementedException( + "Highlighting types for " + leftOperand.getClass().getCanonicalName() + " PsiElements " + + "that are the left operand of " + + matchedWhenOperation.getClass().getCanonicalName() + " is not implemented yet. " + + "Please open an issue (https://github.com/KronicDeth/intellij-elixir/issues/new) " + + "with the class name of the sample text:\n" + matchedWhenOperation.getText() + ); } + + highlightTypesAndSpecificationTypeParameterDeclarations( + matchedWhenOperation.rightOperand(), + typeParameterNameSet, + annotationHolder, + ElixirSyntaxHighlighter.TYPE + ); } } } + + private void highlightTypesAndSpecificationTypeParameterDeclarations(QuotableKeywordPair quotableKeywordPair, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + PsiElement keywordKey = quotableKeywordPair.getKeywordKey(); + + if (typeParameterNameSet.contains(keywordKey.getText())) { + highlight(keywordKey.getTextRange(), annotationHolder, ElixirSyntaxHighlighter.TYPE_PARAMETER); + } else { + highlightTypesAndTypeParameterUsages( + keywordKey, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + highlightTypesAndTypeParameterUsages( + quotableKeywordPair.getKeywordValue(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + private void highlightTypesAndSpecificationTypeParameterDeclarations(PsiElement psiElement, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + if (psiElement instanceof ElixirAccessExpression || + psiElement instanceof ElixirKeywords || + psiElement instanceof ElixirList || + psiElement instanceof ElixirNoParenthesesKeywords) { + highlightTypesAndSpecificationTypeParameterDeclarations( + psiElement.getChildren(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof QuotableKeywordPair) { + highlightTypesAndSpecificationTypeParameterDeclarations( + (QuotableKeywordPair) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else { + throw new NotImplementedException( + "Highlighting types and type parameter declarations for " + + psiElement.getClass().getCanonicalName() + " PsiElements is not implemented yet. Please " + + "open an issue " + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the " + + "class name of the sample text:\n" + psiElement.getText() + ); + } + } + + private void highlightTypesAndSpecificationTypeParameterDeclarations(PsiElement[] psiElements, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + for (PsiElement psiElement : psiElements) { + highlightTypesAndSpecificationTypeParameterDeclarations( + psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + } + + private void highlightTypesAndTypeParameterUsages(Arguments arguments, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey) { + highlightTypesAndTypeParameterUsages( + arguments.arguments(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages(ElixirMapOperation mapOperation, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + highlightTypesAndTypeParameterUsages( + mapOperation.getMapArguments(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages( + ElixirStabOperation stabOperation, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + ElixirStabParenthesesSignature stabParenthesesSignature = stabOperation.getStabParenthesesSignature(); + + if (stabParenthesesSignature != null) { + highlightTypesAndTypeParameterUsages( + stabParenthesesSignature, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else { + ElixirStabNoParenthesesSignature stabNoParenthesesSignatures = stabOperation.getStabNoParenthesesSignature(); + + if (stabNoParenthesesSignatures != null) { + highlightTypesAndTypeParameterUsages( + stabNoParenthesesSignatures, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + } + + ElixirStabBody stabBody = stabOperation.getStabBody(); + + if (stabBody != null) { + highlightTypesAndTypeParameterUsages( + stabBody, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + } + + private void highlightTypesAndTypeParameterUsages( + ElixirStabParenthesesSignature stabParenthesesSignature, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + PsiElement[] children = stabParenthesesSignature.getChildren(); + + if (children.length == 1) { + highlightTypesAndTypeParameterUsages( + children[0], + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (children.length == 3) { + highlightTypesAndTypeParameterUsages( + (WhenOperation) stabParenthesesSignature, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else { + throw new NotImplementedException( + "Highlighting types for " + stabParenthesesSignature.getClass().getCanonicalName() + + " PsiElements with neither 1 nor 3 children is not implemented yet. Please open an " + + "issue (https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name " + + "of the sample text:\n" + stabParenthesesSignature.getText() + ); + } + } + + private void highlightTypesAndTypeParameterUsages( + ElixirStructOperation structOperation, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + highlightTypesAndTypeParameterUsages( + structOperation.getMapArguments(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages( + InfixOperation infixOperation, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + highlightTypesAndTypeParameterUsages( + infixOperation.leftOperand(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + highlightTypesAndTypeParameterUsages( + infixOperation.rightOperand(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages(PsiElement psiElement, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + if (psiElement instanceof Arguments) { + highlightTypesAndTypeParameterUsages( + (Arguments) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof ElixirAccessExpression || + psiElement instanceof ElixirKeywordPair || + psiElement instanceof ElixirKeywords || + psiElement instanceof ElixirList || + psiElement instanceof ElixirMapArguments || + psiElement instanceof ElixirMapConstructionArguments || + psiElement instanceof ElixirNoParenthesesArguments || + psiElement instanceof ElixirNoParenthesesExpression || + psiElement instanceof ElixirParentheticalStab || + psiElement instanceof ElixirStab || + psiElement instanceof ElixirStabBody || + psiElement instanceof ElixirStabNoParenthesesSignature || + psiElement instanceof ElixirTuple) { + highlightTypesAndTypeParameterUsages( + psiElement.getChildren(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof ElixirAlias || + psiElement instanceof ElixirAtom || + psiElement instanceof ElixirAtomKeyword || + psiElement instanceof ElixirBitString || + psiElement instanceof ElixirDecimalWholeNumber || + psiElement instanceof ElixirKeywordKey || + psiElement instanceof ElixirStringLine || + psiElement instanceof ElixirUnaryNumericOperation) { + // leave normal highlighting + } else if (psiElement instanceof ElixirMapOperation) { + highlightTypesAndTypeParameterUsages( + (ElixirMapOperation) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof ElixirRelativeIdentifier || + psiElement instanceof UnqualifiedNoArgumentsCall) { + // highlight entire element + String name = psiElement.getText(); + TextAttributesKey textAttributesKey; + + if (typeParameterNameSet.contains(name)) { + textAttributesKey = ElixirSyntaxHighlighter.TYPE_PARAMETER; + } else { + textAttributesKey = typeTextAttributesKey; + } + + highlight(psiElement.getTextRange(), annotationHolder, textAttributesKey); + } else if (psiElement instanceof ElixirStabParenthesesSignature) { + highlightTypesAndTypeParameterUsages( + (ElixirStabParenthesesSignature) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof ElixirStabOperation) { + highlightTypesAndTypeParameterUsages( + (ElixirStabOperation) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof ElixirStructOperation) { + highlightTypesAndTypeParameterUsages( + (ElixirStructOperation) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof WhenOperation) { + /* NOTE: MUST be before `InfixOperation` as `WhenOperation` is a subinterface of + `InfixOperation` */ + highlightTypesAndTypeParameterUsages( + (WhenOperation) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof InfixOperation) { + highlightTypesAndTypeParameterUsages( + (InfixOperation) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof QualifiedParenthesesCall) { + highlightTypesAndTypeParameterUsages( + (QualifiedParenthesesCall) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof QualifiedAlias) { + highlightTypesAndTypeParameterUsages( + (QualifiedAlias) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof QualifiedNoArgumentsCall) { + highlightTypesAndTypeParameterUsages( + (QualifiedNoArgumentsCall) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof UnqualifiedNoParenthesesCall) { + highlightTypesAndTypeParameterUsages( + (UnqualifiedNoParenthesesCall) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else if (psiElement instanceof UnqualifiedParenthesesCall) { + highlightTypesAndTypeParameterUsages( + (UnqualifiedParenthesesCall) psiElement, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } else { + throw new NotImplementedException( + "Highlighting types for " + psiElement.getClass().getCanonicalName() + + " PsiElements is not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name of the " + + "sample text:\n" + psiElement.getText() + ); + } + } + + private void highlightTypesAndTypeParameterUsages( + PsiElement[] psiElements, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey) { + for (PsiElement psiElement : psiElements) { + highlightTypesAndTypeParameterUsages( + psiElement, + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + } + + private void highlightTypesAndTypeParameterUsages(QualifiedAlias qualifiedAlias, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey) { + highlightTypesAndTypeParameterUsages( + qualifiedAlias.getFirstChild(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + highlightTypesAndTypeParameterUsages( + qualifiedAlias.getLastChild(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages( + QualifiedNoArgumentsCall qualifiedNoArgumentsCall, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey) { + highlightTypesAndTypeParameterUsages( + qualifiedNoArgumentsCall.getFirstChild(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + highlightTypesAndTypeParameterUsages( + qualifiedNoArgumentsCall.getRelativeIdentifier(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages( + QualifiedParenthesesCall qualifiedParenthesesCall, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey) { + highlightTypesAndTypeParameterUsages( + qualifiedParenthesesCall.getFirstChild(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + highlightTypesAndTypeParameterUsages( + qualifiedParenthesesCall.getRelativeIdentifier(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + highlightTypesAndTypeParameterUsages( + qualifiedParenthesesCall.primaryArguments(), + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + + PsiElement[] secondaryArguments = qualifiedParenthesesCall.secondaryArguments(); + + if (secondaryArguments != null) { + highlightTypesAndTypeParameterUsages( + secondaryArguments, + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + } + + private void highlightTypesAndTypeParameterUsages( + UnqualifiedNoParenthesesCall unqualifiedNoParenthesesCall, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + ASTNode functionNameNode = unqualifiedNoParenthesesCall.functionNameNode(); + assert functionNameNode != null; + highlight(functionNameNode.getTextRange(), annotationHolder, typeTextAttributesKey); + + highlightTypesAndTypeParameterUsages( + unqualifiedNoParenthesesCall.primaryArguments(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + + private void highlightTypesAndTypeParameterUsages( + UnqualifiedParenthesesCall unqualifiedParenthesesCall, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + ASTNode functionNameNode = unqualifiedParenthesesCall.functionNameNode(); + assert functionNameNode != null; + highlight(functionNameNode.getTextRange(), annotationHolder, typeTextAttributesKey); + + highlightTypesAndTypeParameterUsages( + unqualifiedParenthesesCall.primaryArguments(), + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + + PsiElement[] secondaryArguments = unqualifiedParenthesesCall.secondaryArguments(); + + if (secondaryArguments != null) { + highlightTypesAndTypeParameterUsages( + secondaryArguments, + typeParameterNameSet, + annotationHolder, + typeTextAttributesKey + ); + } + } + + private void highlightTypesAndTypeParameterUsages( + WhenOperation whenOperation, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey typeTextAttributesKey) { + return; + } + + private void highlightTypesAndSpecificationTypeParameterDeclarations( + ElixirUnmatchedUnqualifiedNoArgumentsCall unmatchedUnqualifiedNoArgumentsCall, + Set typeParameterNameSet, + AnnotationHolder annotationHolder, + TextAttributesKey textAttributesKey + ) { + String variable = unmatchedUnqualifiedNoArgumentsCall.getText(); + + if (typeParameterNameSet.contains(variable)) { + highlight( + unmatchedUnqualifiedNoArgumentsCall.getTextRange(), + annotationHolder, + ElixirSyntaxHighlighter.TYPE_PARAMETER + ); + } else { + highlightTypesAndTypeParameterUsages( + unmatchedUnqualifiedNoArgumentsCall, + typeParameterNameSet, + annotationHolder, + textAttributesKey + ); + } + } + + @NotNull + private Set specificationTypeParameterNameSet(ElixirKeywordPair keywordPair) { + return Collections.singleton(keywordPair.getKeywordKey().getText()); + } + + @NotNull + private Set specificationTypeParameterNameSet(ElixirNoParenthesesKeywordPair noParenthesesKeywordPair) { + return Collections.singleton(noParenthesesKeywordPair.getKeywordKey().getText()); + } + + private Set specificationTypeParameterNameSet(PsiElement psiElement) { + if (psiElement instanceof ElixirAccessExpression || + psiElement instanceof ElixirKeywords || + psiElement instanceof ElixirList || + psiElement instanceof ElixirNoParenthesesKeywords) { + return specificationTypeParameterNameSet(psiElement.getChildren()); + } else if (psiElement instanceof ElixirKeywordPair) { + return specificationTypeParameterNameSet((ElixirKeywordPair) psiElement); + } else if (psiElement instanceof ElixirNoParenthesesKeywordPair) { + return specificationTypeParameterNameSet((ElixirNoParenthesesKeywordPair) psiElement); + } else { + throw new NotImplementedException( + "Extracting specification type parameter name set for " + psiElement.getClass().getCanonicalName() + + " PsiElements is not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name of the " + + "sample text:\n" + psiElement.getText() + ); + } + } + + private Set specificationTypeParameterNameSet(PsiElement[] psiElements) { + Set accumulatedTypeParameterNameSet = new HashSet(); + + for (PsiElement psiElement : psiElements) { + accumulatedTypeParameterNameSet.addAll(specificationTypeParameterNameSet(psiElement)); + } + + return accumulatedTypeParameterNameSet; + } + + private Set typeTypeParameterNameSet( + ElixirMatchedUnqualifiedParenthesesCall matchedUnqualifiedParenthesesCall + ) { + Set typeParameterNameSet = new HashSet(); + + typeParameterNameSet.addAll(typeTypeParameterNameSet(matchedUnqualifiedParenthesesCall.primaryArguments())); + typeParameterNameSet.addAll(typeTypeParameterNameSet(matchedUnqualifiedParenthesesCall.secondaryArguments())); + + return typeParameterNameSet; + } + + private Set typeTypeParameterNameSet(PsiElement psiElement) { + if (psiElement instanceof ElixirUnmatchedUnqualifiedNoArgumentsCall) { + return Collections.singleton(psiElement.getText()); + } else { + throw new NotImplementedException( + "Extracting type type parameter name set for " + psiElement.getClass().getCanonicalName() + + " PsiElements is not implemented yet. Please open an issue " + + "(https://github.com/KronicDeth/intellij-elixir/issues/new) with the class name of the " + + "sample text:\n" + psiElement.getText() + ); + } + } + + private Set typeTypeParameterNameSet(PsiElement[] psiElements) { + Set typeParameerNameSet = new HashSet(); + + for (PsiElement psiElement : psiElements) { + typeParameerNameSet.addAll(typeTypeParameterNameSet(psiElement)); + } + + return typeParameerNameSet; + } } diff --git a/src/org/elixir_lang/psi/Arguments.java b/src/org/elixir_lang/psi/Arguments.java new file mode 100644 index 000000000..a9039960d --- /dev/null +++ b/src/org/elixir_lang/psi/Arguments.java @@ -0,0 +1,13 @@ +package org.elixir_lang.psi; + +import com.intellij.psi.PsiElement; + +/** + * A {@code PsiElement} that has arguments for a {@link org.elixir_lang.psi.call.Call} + */ +public interface Arguments extends PsiElement { + /** + * The actual argument elements for the {@link org.elixir_lang.psi.call.Call}. Used for annotating the arguments. + */ + PsiElement[] arguments(); +} diff --git a/src/org/elixir_lang/psi/AtUnqualifiedNoParenthesesCall.java b/src/org/elixir_lang/psi/AtUnqualifiedNoParenthesesCall.java index e96743ef0..e9b8a9ad1 100644 --- a/src/org/elixir_lang/psi/AtUnqualifiedNoParenthesesCall.java +++ b/src/org/elixir_lang/psi/AtUnqualifiedNoParenthesesCall.java @@ -1,12 +1,12 @@ package org.elixir_lang.psi; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.NoParentheses; +import org.elixir_lang.psi.call.arguments.NoParenthesesOneArgument; /** * atPrefixOperator IDENTIFIER CALL bracketArguments */ -public interface AtUnqualifiedNoParenthesesCall extends Call, Quotable { +public interface AtUnqualifiedNoParenthesesCall extends Call, NoParenthesesOneArgument, Quotable { Quotable getAtPrefixOperator(); - - QuotableArguments getNoParenthesesOneArgument(); } diff --git a/src/org/elixir_lang/psi/DotCall.java b/src/org/elixir_lang/psi/DotCall.java index f09596aaa..bae88d77d 100644 --- a/src/org/elixir_lang/psi/DotCall.java +++ b/src/org/elixir_lang/psi/DotCall.java @@ -1,6 +1,10 @@ package org.elixir_lang.psi; +import com.intellij.psi.PsiElement; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.Parentheses; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -11,4 +15,13 @@ public interface DotCall extends Call, Quotable { Quotable getDotInfixOperator(); List getParenthesesArgumentsList(); + + /** + * Unlike with a base {@link Call}, {@link Parentheses#primaryArguments} are {@code @NotNull} because the first set + * of parentheses has to be there or it wouldn't be a {@link Parentheses} + */ + @Contract(pure = true) + @Override + @NotNull + PsiElement[] primaryArguments(); } diff --git a/src/org/elixir_lang/psi/QualifiedNoArgumentsCall.java b/src/org/elixir_lang/psi/QualifiedNoArgumentsCall.java index ceb6aaeac..5e946d523 100644 --- a/src/org/elixir_lang/psi/QualifiedNoArgumentsCall.java +++ b/src/org/elixir_lang/psi/QualifiedNoArgumentsCall.java @@ -1,9 +1,10 @@ package org.elixir_lang.psi; +import org.elixir_lang.psi.call.arguments.None; import org.elixir_lang.psi.call.qualification.Qualified; /** * dotInfixOperator relativeIdentifier !CALL */ -public interface QualifiedNoArgumentsCall extends Qualified, Quotable { +public interface QualifiedNoArgumentsCall extends None, Qualified, Quotable { } diff --git a/src/org/elixir_lang/psi/QualifiedNoParenthesesCall.java b/src/org/elixir_lang/psi/QualifiedNoParenthesesCall.java index fbdb450fc..a32b8d2b1 100644 --- a/src/org/elixir_lang/psi/QualifiedNoParenthesesCall.java +++ b/src/org/elixir_lang/psi/QualifiedNoParenthesesCall.java @@ -1,10 +1,10 @@ package org.elixir_lang.psi; +import org.elixir_lang.psi.call.arguments.NoParenthesesOneArgument; import org.elixir_lang.psi.call.qualification.Qualified; /** * dotInfixOperator relativeIdentifier noParenthesesOneArgument */ -public interface QualifiedNoParenthesesCall extends Qualified, Quotable { - ElixirNoParenthesesOneArgument getNoParenthesesOneArgument(); +public interface QualifiedNoParenthesesCall extends NoParenthesesOneArgument, Qualified, Quotable { } diff --git a/src/org/elixir_lang/psi/QualifiedParenthesesCall.java b/src/org/elixir_lang/psi/QualifiedParenthesesCall.java index 8066bc946..86d7008f6 100644 --- a/src/org/elixir_lang/psi/QualifiedParenthesesCall.java +++ b/src/org/elixir_lang/psi/QualifiedParenthesesCall.java @@ -1,10 +1,10 @@ package org.elixir_lang.psi; +import org.elixir_lang.psi.call.arguments.Parentheses; import org.elixir_lang.psi.call.qualification.Qualified; /** * dotInfixOperator relativeIdentifier matchedParenthesesArguments */ -public interface QualifiedParenthesesCall extends Qualified, Quotable { - ElixirMatchedParenthesesArguments getMatchedParenthesesArguments(); +public interface QualifiedParenthesesCall extends Parentheses, Qualified, Quotable { } diff --git a/src/org/elixir_lang/psi/UnqualifiedNoArgumentsCall.java b/src/org/elixir_lang/psi/UnqualifiedNoArgumentsCall.java index 00e5574be..314aa01b2 100644 --- a/src/org/elixir_lang/psi/UnqualifiedNoArgumentsCall.java +++ b/src/org/elixir_lang/psi/UnqualifiedNoArgumentsCall.java @@ -1,10 +1,11 @@ package org.elixir_lang.psi; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.None; import org.elixir_lang.psi.qualification.Unqualified; /** * IDENTIFIER !KEYWORD_PAIR_COLON doBlock? */ -public interface UnqualifiedNoArgumentsCall extends Call, Quotable, Unqualified { +public interface UnqualifiedNoArgumentsCall extends None, Call, Quotable, Unqualified { } diff --git a/src/org/elixir_lang/psi/UnqualifiedNoParenthesesCall.java b/src/org/elixir_lang/psi/UnqualifiedNoParenthesesCall.java index 5b87f4c53..cdd029fbe 100644 --- a/src/org/elixir_lang/psi/UnqualifiedNoParenthesesCall.java +++ b/src/org/elixir_lang/psi/UnqualifiedNoParenthesesCall.java @@ -1,15 +1,18 @@ package org.elixir_lang.psi; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.NoParentheses; +import org.elixir_lang.psi.call.arguments.NoParenthesesOneArgument; import org.elixir_lang.psi.qualification.Unqualified; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; /** * IDENTIFIER noParenthesesOneArgument */ -public interface UnqualifiedNoParenthesesCall extends Call, Quotable, Unqualified { +public interface UnqualifiedNoParenthesesCall extends Call, NoParenthesesOneArgument, Quotable, Unqualified { + @Contract(pure = true) @NotNull + @Override String functionName(); - - ElixirNoParenthesesOneArgument getNoParenthesesOneArgument(); } diff --git a/src/org/elixir_lang/psi/UnqualifiedParenthesesCall.java b/src/org/elixir_lang/psi/UnqualifiedParenthesesCall.java index 7929b3653..75ba49538 100644 --- a/src/org/elixir_lang/psi/UnqualifiedParenthesesCall.java +++ b/src/org/elixir_lang/psi/UnqualifiedParenthesesCall.java @@ -1,11 +1,11 @@ package org.elixir_lang.psi; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.Parentheses; import org.elixir_lang.psi.qualification.Unqualified; /** - * IDENTIFIER matchedParenthesesArguments + * {@code IDENTIFIER matchedParenthesesArguments} */ -public interface UnqualifiedParenthesesCall extends Call, Quotable, Unqualified { - ElixirMatchedParenthesesArguments getMatchedParenthesesArguments(); +public interface UnqualifiedParenthesesCall extends Call, Parentheses, Quotable, Unqualified { } diff --git a/src/org/elixir_lang/psi/WhenOperation.java b/src/org/elixir_lang/psi/WhenOperation.java new file mode 100644 index 000000000..7f9d2c0f2 --- /dev/null +++ b/src/org/elixir_lang/psi/WhenOperation.java @@ -0,0 +1,7 @@ +package org.elixir_lang.psi; + +/** + * ... when ... + */ +public interface WhenOperation extends InfixOperation { +} diff --git a/src/org/elixir_lang/psi/call/Call.java b/src/org/elixir_lang/psi/call/Call.java index 7425c30a6..39ad5b4d5 100644 --- a/src/org/elixir_lang/psi/call/Call.java +++ b/src/org/elixir_lang/psi/call/Call.java @@ -1,13 +1,14 @@ package org.elixir_lang.psi.call; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.elixir_lang.psi.ElixirDoBlock; import org.jetbrains.annotations.Nullable; /** * A general function or macro call. */ -public interface Call { +public interface Call extends PsiElement { /** * * @return name of the function/macro as given in the source @@ -35,6 +36,26 @@ public interface Call { @Nullable String moduleName(); + /** + * The arguments directly after the {@link #functionName}. If the function cannot have arguments, then this will `null` + * + * @return {@code null} if function cannot take arguments, such as an ambiguous variable or no parentheses, + * no arguments, function call like {@code foo}. + * @return {@code PsiElement[]} if the function takes arguments. Importantly, {@code foo} can be distinguished from + * {@code foo()} because the formmer returns {@code null} while the latter returns {@code new PsiElement[0]} + */ + @Nullable + PsiElement[] primaryArguments(); + + /** + * The arguments in the second set of parentheses. + * + * @return {@code null} if the call cannot or does not have a second set of parentheses. + * @return {@code PsiElement[]} + */ + @Nullable + PsiElement[] secondaryArguments(); + /** * @return name of the function/macro after taking into account any imports */ diff --git a/src/org/elixir_lang/psi/call/arguments/NoParentheses.java b/src/org/elixir_lang/psi/call/arguments/NoParentheses.java new file mode 100644 index 000000000..61ed97a7c --- /dev/null +++ b/src/org/elixir_lang/psi/call/arguments/NoParentheses.java @@ -0,0 +1,33 @@ +package org.elixir_lang.psi.call.arguments; + +import com.intellij.psi.PsiElement; +import org.elixir_lang.psi.ElixirMatchedParenthesesArguments; +import org.elixir_lang.psi.ElixirNoParenthesesOneArgument; +import org.elixir_lang.psi.call.Call; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A call with no parentheses around the arguments + * + * {@code <...> noParenthesesOneArgument} + */ +public interface NoParentheses extends Call { + /** + * Unlike with a base {@link Call}, {@link NoParentheses#primaryArguments} are {@code @NotNull} because the first + * set of arguments has to be there or it would be a {@link None} + */ + @Contract(pure = true) + @Override + @NotNull + PsiElement[] primaryArguments(); + + /** + * @return Always {@code null} because without parentheses, there is no way to separate sets of arguments. + */ + @Contract(pure = true, value = "-> null") + @Override + @Nullable + PsiElement[] secondaryArguments(); +} diff --git a/src/org/elixir_lang/psi/call/arguments/NoParenthesesOneArgument.java b/src/org/elixir_lang/psi/call/arguments/NoParenthesesOneArgument.java new file mode 100644 index 000000000..892b428e0 --- /dev/null +++ b/src/org/elixir_lang/psi/call/arguments/NoParenthesesOneArgument.java @@ -0,0 +1,14 @@ +package org.elixir_lang.psi.call.arguments; + +import org.elixir_lang.psi.ElixirNoParenthesesOneArgument; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * Created by limhoff on 12/17/15. + */ +public interface NoParenthesesOneArgument extends NoParentheses { + @Contract(pure = true) + @NotNull + ElixirNoParenthesesOneArgument getNoParenthesesOneArgument(); +} diff --git a/src/org/elixir_lang/psi/call/arguments/None.java b/src/org/elixir_lang/psi/call/arguments/None.java new file mode 100644 index 000000000..26684eb63 --- /dev/null +++ b/src/org/elixir_lang/psi/call/arguments/None.java @@ -0,0 +1,31 @@ +package org.elixir_lang.psi.call.arguments; + +import com.intellij.psi.PsiElement; +import org.elixir_lang.psi.ElixirMatchedParenthesesArguments; +import org.elixir_lang.psi.call.Call; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A call with no arguments; not even empty parentheses. + */ +public interface None extends Call { + /** + * @return Always {@code null} because a no argument call by definition has no arguments, not even an empty list + * of arguments. + */ + @Contract(pure = true, value = "-> null") + @Override + @Nullable + PsiElement[] primaryArguments(); + + /** + * @return Always {@code null} because a no argument call doesn't ever have {@link #primaryArguments}, so it can't + * have secondary arguments. + */ + @Contract(pure = true, value = "-> null") + @Override + @Nullable + PsiElement[] secondaryArguments(); +} diff --git a/src/org/elixir_lang/psi/call/arguments/Parentheses.java b/src/org/elixir_lang/psi/call/arguments/Parentheses.java new file mode 100644 index 000000000..d356d2f00 --- /dev/null +++ b/src/org/elixir_lang/psi/call/arguments/Parentheses.java @@ -0,0 +1,27 @@ +package org.elixir_lang.psi.call.arguments; + +import com.intellij.psi.PsiElement; +import org.elixir_lang.psi.ElixirMatchedParenthesesArguments; +import org.elixir_lang.psi.call.Call; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * A call with one or two sets of parentheses containing arguments inside a {@code matchedParenthesesArguments} + * + * {@code <...> matchedParenthesesArguments} + */ +public interface Parentheses extends Call { + @Contract(pure = true) + @NotNull + ElixirMatchedParenthesesArguments getMatchedParenthesesArguments(); + + /** + * Unlike with a base {@link Call}, {@link Parentheses#primaryArguments} are {@code @NotNull} because the first set + * of parentheses has to be there or it wouldn't be a {@link Parentheses} + */ + @Contract(pure = true) + @Override + @NotNull + PsiElement[] primaryArguments(); +} diff --git a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java index 8dc953d27..c7903be0c 100644 --- a/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java +++ b/src/org/elixir_lang/psi/impl/ElixirPsiImplUtil.java @@ -13,6 +13,10 @@ import org.elixir_lang.Macro; import org.elixir_lang.psi.*; import org.elixir_lang.psi.call.Call; +import org.elixir_lang.psi.call.arguments.NoParentheses; +import org.elixir_lang.psi.call.arguments.NoParenthesesOneArgument; +import org.elixir_lang.psi.call.arguments.None; +import org.elixir_lang.psi.call.arguments.Parentheses; import org.elixir_lang.psi.qualification.Qualified; import org.elixir_lang.psi.qualification.Unqualified; import org.jetbrains.annotations.Contract; @@ -73,6 +77,74 @@ public class ElixirPsiImplUtil { public static final int UNKNOWN_BASE = 36; public static final TokenSet IDENTIFIER_TOKEN_SET = TokenSet.create(ElixirTypes.IDENTIFIER); + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(@NotNull final ElixirMapConstructionArguments mapConstructionArguments) { + return mapConstructionArguments.getChildren(); + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(ElixirNoParenthesesManyArguments noParenthesesManyArguments) { + Arguments arguments = noParenthesesManyArguments.getNoParenthesesOnePositionalAndKeywordsArguments(); + + if (arguments == null) { + arguments = noParenthesesManyArguments.getNoParenthesesManyPositionalAndMaybeKeywordsArguments(); + } + + return arguments.arguments(); + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(@NotNull final ElixirNoParenthesesOneArgument noParenthesesOneArgument) { + PsiElement[] children = noParenthesesOneArgument.getChildren(); + + assert children.length == 1; + + PsiElement child = children[0]; + PsiElement[] arguments; + + if (child instanceof Arguments) { + Arguments childArguments = (Arguments) child; + arguments = childArguments.arguments(); + } else { + arguments = children; + } + + return arguments; + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(ElixirNoParenthesesManyPositionalAndMaybeKeywordsArguments noParenthesesManyPositionalAndMaybeKeywordsArguments) { + return noParenthesesManyPositionalAndMaybeKeywordsArguments.getChildren(); + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(@NotNull final ElixirNoParenthesesOnePositionalAndKeywordsArguments noParenthesesOnePositionalAndKeywordsArguments) { + PsiElement noParenthesesFirstPositional = noParenthesesOnePositionalAndKeywordsArguments.getNoParenthesesFirstPositional(); + PsiElement noParenthesesKeywords = noParenthesesOnePositionalAndKeywordsArguments.getNoParenthesesKeywords(); + + return new PsiElement[]{ + noParenthesesFirstPositional, + noParenthesesKeywords + }; + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(@NotNull final ElixirNoParenthesesStrict noParenthesesStrict) { + return noParenthesesStrict.getChildren(); + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] arguments(@NotNull final ElixirParenthesesArguments parenthesesArguments) { + return parenthesesArguments.getChildren(); + } + @Contract(pure = true) @NotNull public static int base(@SuppressWarnings("unused") @NotNull final ElixirBinaryDigits binaryDigits) { @@ -725,6 +797,52 @@ public static TokenSet operatorTokenSet(@SuppressWarnings("unused") final Elixir return TokenSet.create(ElixirTypes.WHEN_OPERATOR); } + @Contract(pure = true) + @NotNull + public static PsiElement[] primaryArguments(@NotNull final DotCall dotCall) { + List parenthesesArgumentsList = dotCall.getParenthesesArgumentsList(); + + ElixirParenthesesArguments primaryParenthesesArguments = parenthesesArgumentsList.get(0); + return primaryParenthesesArguments.arguments(); + } + + @Contract(pure = true) + @Nullable + public static PsiElement[] primaryArguments(@NotNull final ElixirUnqualifiedNoParenthesesManyArgumentsCall unqualifiedNoParenthesesManyArgumentsCall) { + Arguments arguments = unqualifiedNoParenthesesManyArgumentsCall.getNoParenthesesManyArguments(); + + if (arguments == null) { + arguments = unqualifiedNoParenthesesManyArgumentsCall.getNoParenthesesStrict(); + } + + assert arguments != null; + + return arguments.arguments(); + } + + @Contract(pure = true) + @Nullable + public static PsiElement[] primaryArguments(@NotNull @SuppressWarnings("unused") final None none) { + return null; + } + + + @Contract(pure = true) + @NotNull + public static PsiElement[] primaryArguments(@NotNull final NoParenthesesOneArgument noParenthesesOneArgument) { + return noParenthesesOneArgument.getNoParenthesesOneArgument().arguments(); + } + + @Contract(pure = true) + @NotNull + public static PsiElement[] primaryArguments(@NotNull final Parentheses parentheses) { + ElixirMatchedParenthesesArguments matchedParenthesesArguments = parentheses.getMatchedParenthesesArguments(); + List parenthesesArgumentsList = matchedParenthesesArguments.getParenthesesArgumentsList(); + + ElixirParenthesesArguments primaryParenthesesArguments = parenthesesArgumentsList.get(0); + return primaryParenthesesArguments.arguments(); + } + public static boolean processDeclarations(@NotNull final ElixirAccessExpression accessExpression, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @@ -3053,21 +3171,21 @@ public static OtpErlangObject[] quoteArguments(@NotNull final ElixirDoBlock doBl @Contract(pure = true) @NotNull public static OtpErlangObject[] quoteArguments(@NotNull final ElixirMapConstructionArguments mapConstructionArguments) { - PsiElement[] children = mapConstructionArguments.getChildren(); - List quotedChildList = new ArrayList(); + PsiElement[] arguments = mapConstructionArguments.arguments(); + List quotedArgumentList = new ArrayList(); - for (PsiElement child : children) { - Quotable quotableChild = (Quotable) child; - OtpErlangList quotedChild = (OtpErlangList) quotableChild.quote(); + for (PsiElement argument : arguments) { + Quotable quotableArgument = (Quotable) argument; + OtpErlangList quotedArgument = (OtpErlangList) quotableArgument.quote(); - for (OtpErlangObject element : quotedChild.elements()) { - quotedChildList.add(element); + for (OtpErlangObject element : quotedArgument.elements()) { + quotedArgumentList.add(element); } } - OtpErlangObject[] quotedArguments = new OtpErlangObject[quotedChildList.size()]; + OtpErlangObject[] quotedArguments = new OtpErlangObject[quotedArgumentList.size()]; - return quotedChildList.toArray(quotedArguments); + return quotedArgumentList.toArray(quotedArguments); } @Contract(pure = true) @@ -3114,6 +3232,7 @@ public static OtpErlangObject[] quoteArguments(ElixirNoParenthesesManyPositional return quotedChildren; } + @Contract(pure = true) @NotNull public static OtpErlangObject[] quoteArguments(@NotNull final ElixirNoParenthesesOneArgument noParenthesesOneArgument) { @@ -3184,12 +3303,12 @@ public static OtpErlangObject[] quoteArguments(ElixirNoParenthesesStrict noParen @Contract(pure = true) @NotNull public static OtpErlangObject[] quoteArguments(ElixirParenthesesArguments parenthesesArguments) { - PsiElement[] children = parenthesesArguments.getChildren(); + PsiElement[] arguments = parenthesesArguments.arguments(); - OtpErlangObject[] quotedArguments = new OtpErlangObject[children.length]; + OtpErlangObject[] quotedArguments = new OtpErlangObject[arguments.length]; - for (int i = 0; i < children.length; i++) { - Quotable quotableChild = (Quotable) children[i]; + for (int i = 0; i < arguments.length; i++) { + Quotable quotableChild = (Quotable) arguments[i]; OtpErlangObject quotedChild = quotableChild.quote(); quotedArguments[i] = quotedChild; } @@ -3571,6 +3690,51 @@ public static Quotable rightOperand(InfixOperation infixOperation) { return (Quotable) children[2]; } + @Contract(pure = true) + @Nullable + public static PsiElement[] secondaryArguments(@NotNull final DotCall dotCall) { + List parenthesesArgumentsList = dotCall.getParenthesesArgumentsList(); + PsiElement[] arguments; + + if (parenthesesArgumentsList.size() < 2) { + arguments = null; + } else { + ElixirParenthesesArguments parenthesesArguments = parenthesesArgumentsList.get(1); + arguments = parenthesesArguments.arguments(); + } + + return arguments; + } + + @Contract(pure = true, value = "_ -> null") + @Nullable + public static PsiElement[] secondaryArguments(@NotNull @SuppressWarnings("unused") final None none) { + return null; + } + + @Contract(pure = true, value = "_ -> null") + @Nullable + public static PsiElement[] secondaryArguments(@NotNull @SuppressWarnings("unused") final NoParentheses noParentheses) { + return null; + } + + @Contract(pure = true) + @Nullable + public static PsiElement[] secondaryArguments(@NotNull final Parentheses parentheses) { + ElixirMatchedParenthesesArguments matchedParenthesesArguments = parentheses.getMatchedParenthesesArguments(); + List parenthesesArgumentsList = matchedParenthesesArguments.getParenthesesArgumentsList(); + PsiElement[] arguments; + + if (parenthesesArgumentsList.size() < 2) { + arguments = null; + } else { + ElixirParenthesesArguments parenthesesArguments = parenthesesArgumentsList.get(1); + arguments = parenthesesArguments.arguments(); + } + + return arguments; + } + @NotNull public static PsiElement setName(@NotNull PsiElement element, @NotNull String newName) { return null; diff --git a/src/org/elixir_lang/psi/qualification/Unqualified.java b/src/org/elixir_lang/psi/qualification/Unqualified.java index 16f9b24c5..1ad16cb63 100644 --- a/src/org/elixir_lang/psi/qualification/Unqualified.java +++ b/src/org/elixir_lang/psi/qualification/Unqualified.java @@ -1,6 +1,9 @@ package org.elixir_lang.psi.qualification; +import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; /** * IDENTIFIER ... From 2061f08b9b1df779d97fec192b82f946e4e49f1c Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 24 Dec 2015 15:29:54 -0600 Subject: [PATCH 10/10] Module Attribute example test and screenshot --- screenshots/annotator/Module Attribute.png | Bin 0 -> 143407 bytes .../module_attribute/module_attributes.ex | 50 ++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 screenshots/annotator/Module Attribute.png create mode 100644 testData/org/elixir_lang/annotator/module_attribute/module_attributes.ex diff --git a/screenshots/annotator/Module Attribute.png b/screenshots/annotator/Module Attribute.png new file mode 100644 index 0000000000000000000000000000000000000000..7600bafabdea61ffb1d976c5d9754b7ae4d126f2 GIT binary patch literal 143407 zcmZs?1C(V;(=A%A>SC8|+qP|Y*|uHPW!tuG+qP}ndVS7!{_}tL-nYltd#s%qk+~8p zB4fr}p>i^!FpwCK0000m;$lJy002M*f4+ARV1G)WV}}I){Gyr(3d)HK3gXGx+ZdZ! z8UX-^g(fD0D=Cg*3?C;U2?#(5@kyLW$7mM@p|m;Hz{kY|APC@UVw%{N9otIZm z(9{S}r*dHgf8oV1WMrg8rOSUPjlh?Eed%^Q$?kA{?S1dH{W-mn>R}8Z=W-}U)LH@t z;I>C#=Bf6Rk(oME{0+DS0Hz0^Nf#+tgX~8{csS6v+M5lqkaxEp?eycc_jjY|-AkY* zKn&YRYKMR|&OtxG&YNav0|bBoWkb3&b==4+wxJa{5(Gdjm5E;*%t1z}p=hA2J{Ocd z9e^Q4Fd;HP4$1U1)e)pF4)YH~QF>XTpbpSFT-A|Xe(PW^5?Wf^Iu7JIrz00Pknbc$ z2O`p7LNq-i9i%`kDvE>y`=amc{@ZRz?JCO`?4lZlz_}Y&x9r`P%dyeu1jdCZEJTx` z0fD98p7H~VFXOLWawu6$2iyJBhQ0Lu+vqvI!#|<|pobBRM(pE&f>%-rl?McTm_(EY zWU%(6%)CG3yc<$<(BkMO1b8^j$&U5ytS9JHO+p1$V|Jwk;gTT`6%#mS>j(1=&_>K- zG@u+12!cOwlOfdU`*{@9J2dOr4_wseW?T#5iqcitHfSgO#^p_C0jB<%NtK5EUqt<^g0GireY2Y>X}E{E@cC`JK4 z5v3!-7cWFVN`~zrB(B+F2?3%&fJx!`Gb0}OTjH6Ynw|K`jwQ+U04m@Cc-nGmac4 z>YfChMNtRMEek)H{FRgOBafdm0t)*~izMO-=c$)E*PN9L;yLgw*Ez%Q9N1$6`HAS~ zbFi0#|I#(`n23@m<~Z&)>GHD|Zt#V9lex7Z1%v2Ay-0`mMBkfrgzF8?Yd&cc8fSo3 zkBmWbje#1lu0Cn4$OVP7<`g00ZmB*AbT_qjE;aZOJj^@W61y{}_g8eYLlBY}@-`;Y zZ87pFDhQM0kqdP4t9G-JoVLy_AV4DJ#Iix69%6KDFTOwg_5s_bQ|e;Epm_ zb}>Iyj0rgUaG-8 z!ISPeW`wTyzoJKx?rL@bWJl5tvhK9sxPMT217G)e+*X5N^!n|=ss8p_JbipsQ$w`By2t!3v*a3$JG zmvWzCi+O7b>Io6CIFHnkBJ~BJGjnFb4Mq*W*3j1s*1(zD()=+rB8yo> zD}KOP@_kOx4V5nAkAtnah}>%r|CF<_j!1%!bU5 z%xD%jD&55I15w1s6)1(miyP%E(wERHWjI7w^XpGE-+)Fx(knA7wW>N* z+lAXzMJ0!oN!3l#WD=+BGM&MOY7A@8TO$r5{3F&QWb>g#L8JDfe=(SEmz?KsokuOf z%p9I4on9?>7QTx|m!jq+=Qk@<^IymERN0jCYWtLVH-52yX3ehUdx$Va z>stJ@q3hR8?^X8a5hU!V6AayT?`I6+7J<$O$hXX26d{dhi##3j9wOLZ93qYUHaw#P zPHmlVny8=9Mg)$xMNA!4iARYCRHU3Intv^Nm&Q$%pWvFTn@~w-PJc|pOcza`W~yfF zw#n7sHN$UEv#{&k>nuz(3Oghi2OCFKX;ZN*M=0kg4_;!j@Hq!M$2d=C5yF&B$4ZxG zscb5#Os|}28hc8^Hb1r|ty?!-W(lGjvWRe%noQw*QhMim*MH}DhXoH3Oz8Iv1`Ad- zm>e#O)?$C^Td9t+j%tls$HrwdV;5$dbTPMg-?u!UaH_KJIu&sE;gq^RcXGG3IF)$) z>(YHW@(Sg$X{2)XGQ2&weZec+qdB-$G-y~Pnlo!H%Pvcjo7Nq^<9ElAEB5`{$>o*S zf!EBt4X#HvR`wDoPNKnjhZc*;U3k;yMh4HQiZwZ-RU5eu1%;^*S$T?(G1AyR9M1(t=HLkkgYWb4wHtmX$i^wjxHw9C!|L=vqh)IM>r{#5ROBpk1!8q z$8F+Q#3hI?LAO9HAl(aN=dc6Cb_@E32&`HbTPf<3K8eoBo+zs*zUY|U&T`Gt<_G4h zWSTR(4BzhKX5w^=cNkk3(@fGPGFa;kRCX#V>tk0_>(h@@Ce_)BEv#2IwC>67?Tb)%LVH53i2G3AIjbqCl-y$w<}ZY zjuZ+l4v!iW8tWP_&-0d;t5|iq^*@hc`e2&NewRJjFs-y0?!QZSNH3QImpxmtY-o19 z&ZEpGwQKY@EiJ1pDOnR*Q*J$3dfYuhb-R8kvujez`+TK!lQo&Z1&pb&;?yJ8sx< zG`UYW0yj~Z-r(Z=vK((6aX_68&f;~zzv&wd??R2%y6bX$s5?FkqP$W)t8UZczH48< z7X7uMaaQf7X<_+jZe@z&!|{InKS_H33i z539HKd*AC|?bXcH5-;h;>Z8J)eNOQM?PNDgSDm-h%e8NJ^;6N4b7xW)j%WQt<<@%U zwdOYS^WY=*)$}>8tIiYub$?ZK7A~!)#Os5n?wQHlv6GHv7n4`y$D1vkjjdc?tUZzj zAhZe-C6q5KCtyxtZznL3;8F|9Cvf{6&IpO5|_y0rWT;0ihb-<&2u-VRP7h6>b( zl54U}HzF{=*&c&Ju!LSxcs&Cua+W>>E*SVW1`wY)&`!9ct*!3-&Q9{B+yys)3^LiY z*PTFs#|O2+;lkP@;6z7dV9mF=Gp z0sw%^mE+H)m64+!o~xCmwF8GMH^JW$9DlC=DyAjC`&-1(f}221S`JUp#@+~znTCmm zj(`Ue4-b#a-q4ssK}h5u^*{f(2}~UwZ8>OZU0hsfTo`F=>`iFt+1c4?=@@7k7^we9 zP&>F;JLgeCkf9})B)$D(J zvUd1qSbqjc`&SJuJq;c0zit0f<@&3XL(a_A$Wl$n%*x2x;ZGktEUYYCf6MFJSIs|~T(o};;J*g+pV|7m^v`thKyuOkJM}z}Hr<27004Xd;zImN zu7DSvKQuK}-DzJ`t>mZ%yO2si^pO!DW`08tB^j!R6E{;gS6;DYTD5Ig$4hOc9T<6k z7R8T_SChUP#f?s+PY}7Saxjj1U=MHFty{Gdud2oQ*9HcF0QvFhQv>Q3hZTmcF>SXt zmyzvkDGHZ1tneIzJ0&|zxpZCoba_m>bk|#zR#tYx!Giz+0s8s!@!{e9{0RX80s<8M z15nG;^TUAR7ZT+^MgK|wFad%5AHsiXdiI5O?u}y3=H)fz{l>;1)ui5rL)TGDED^^b zrm6OS#Y!FNCm&;dcu1Kk^^@@Po0qREC2T(I`BTfd-f^Gq+lTwF*W7H&>c z-=0o*Lb_A*9(5EucZmW9qY{yM&M2zhXX^N5n+ zS_yCVCG^~pU$eHkL8Y@b68YFulXA)xe6Lk+p+|2eXr+vNL|02J`SHg`nF?TC`g zPUQicFU1&AR4!<7>S|fGs#iHZb9bhsCbl zpDe-|WFY8D&5#)?fy=z^^sBP9vKbKSZuwE@UgMl^u>t6>lH{+PBu0n$l*>`PCF2q{M5%y4`|Q@I-0O#fZ5Z2trO&5aY`8cjK}F$d(c18 zqny#b0e2E^clW?kP&1U!SA{yIi;8SteOcTx@FF)pj3BCvvv0@i2n7`~E(R>9t5<<2 zo!s_85{`om6I|PlCy3*FuFmIj&+Zrz-<;GRKC2Mf@5C9~2ccj)^{{vGYN5$ka&a@h zg3Rilj?Fs5S{2nQWp_zi4nFM48uZ5M9xFWvZd*_#R;GAdrx-^cv#z${iwdW1<#2E3NQbeCj!6UOC2-Q2qEGwM zHR;C69cA}0@6gIqGKP0s{lRt8e=-nXa39w}@mO4RKlka*C~{(OP?uQ4GS|L42s{(1 zJ=9Ju=vewuA!cNEmbq+cN3ZDCeUmjgOZDYYP61rJh5l`^h5t}xXdpUNl`(jTALXc- z=B|Xx6NTM6`eiZ^=+Rl(Vmk>r-eq7)mbl%Fa}1=}W=M46*|Pi!PvaOHF9e$W$kFx1 z@oRN?UfrW|i>HL!fa~>YU|EEe6Z|~*c4H1oyzvW-X990>%M04%451(^v(--}!|0L| zlv%T`EPAIEVJ9D#8Pr3qJi7BY!L?P#qR@3G*|`=st_~PUzWzEd?Rc`bJzDjZw0sRZ z5k2cy&GYE!CtX#Gu9ys7Cu#dJ%PO}jI*p!d?3wClQd4C>@0Va??DG7QaT!cPR%Zn`Jaa_7PY0d6}g{tB80hqT$X!B;{Nv>WCZ_eB zOeTX3|1;b37UW5dj1m210*#qU?e=s~WyR@2QBVcT*-;8QZ~qNOs&zj$BlS0*T~w*J zrcGzmEGR(-T^MXx{L>Rngv4bux+q*M{aLz@h6AIu>|2bg6T~}^pq%pg=j@*ThH+BF zO=|5AlC!p-B49}zIZGDyL8GV!tLn4i;}0`LNV{rI06Wakr8;tprwlIp2chw7Zg)i5 zp0`9#^qF{@%9XrR_dUy@q8iOorplRcczJ3*SedwOzxmSvg(HK1;B!A=mx`uM1w~N` zA_zB{2!|6z}GYH_Yc0;Yqlx}_>*aL{OKlQB@N z_WwL=gfpK;ljYIIQgw!1^32>h#glb?d^2cG;V%na)~iW$FDjvy&42pTrT^Y!WM%=6 z#K+_;bQJ1Q3qrs!Z)9K?W}rz=jJROwb~*QlEZZ|x}wUL z`&?GvODZQSc|uj40fSuq9~wQXI}zi2rnm9fDj%E{2z;;~A7d7^oz*Zf&C}C@SP0?3 zk|VWwS4SES0Jynpo}LXb)@$N1rc=9k9>hg{jyL~hpGc)&hznhYLw@Z< zNbuz{_43-kIl2xYo+b4Wo3U!nyqf2QERU_uoD<5@VKz z4rO;=V%QX;V^xSf1OT05C!cvFe+zGY9t_v{7=Q*(S?_q{F*)0A=I6_{`f<9I3KP|Js+FGtRlG*l9ZK z!V5u$WQoUTx-5+)wz5TB<(!2ssu;L)anB!x3ug zd@k$}3PMrHjFW<=`0cH-=<8!{(TOFwM7^>6U(Iw!Vt3?vlZ&X|_qy$y0xfd=t2Tt1 zGWgvsF&M@;v}a8);GTYC2y}yu&AjZYSCHh&~o06m;5M7^fpe@bl4h=a@ zgEE0uxcF3*MtGH<#iR&;wm)t#9JUn0qZ9M$utNU4A@ zl3saZS)rGVb}RL~`w`g1+$?QWms_RjqkU>r{=qe32o!yUk+;CdP0oRPKq-|RP&XC5 zU!R4ZQ8wmlQWPHXjn}vnYR~g(RPj^=WvuOx7p0DudiO3IrCb$!V@DMj2Q6iTe7;FJ z58V}Tl>8gF>I-erpF%pV!TrLK&{POUbIK@>G};Q%8$nV>R`H-DM;1E_Bb%hZCghab zBO8!Qvj8L`TY7XVS8!9k>=O8yyB7mc`PJ2qYt`*Cg({$~tK=N7xe`**r(!Gl$kM)7 zERIJ7{aI6UWbG8Q3BP(l;A;lfk}{8cvPt_iKYc?`A*5*w`QFY*u3BR#q)dCMz7A^e2K6mr%j8dZCi-BF(^-uKxnC^?vt)Cs*FbMIdr7lyw zCSy6O{!onf62{{}6>|>EybEFD=g_&#;C809f3SmOTh`Uk2=c?fxAX!#ppIqF*;P65eR9$+A{qBW71k1KYk5W=wDP89x^bj z!~m#Z8<=))MP}tX8A;Y+`ZW9kg%aMI2j%o?l<K`wD-g`x@J3YcOcAHA~Ex{->4k7ioM5}pIh8p9zH9cqPNza=C zCqO=@{aI?ygtD*BAhLVQpDgbm)Q8_t@tz_-O1`a9;-c-|c&tY>@g6vuk+Qf~Y)?%8Y#=O#-Xxa{+^B z5^*nC4*~uPrqFPqHQ@0)6D+!o$5qI@(s~Ubbr8|&avvq-Pukv%Gzd(ZUAhM$3hw5F zNoH36Mj%;jqD@0yv4;RV%@=yUj_ln9k-hG8O~oVagnqz^u+N026JxO$zmxwnEw8l{ zbYhj+E&oU5l2Kj2l>+MR>&=!tFMK7F1$zR)_Xdw4v1kYEq9}$g3p#OrWgH3YB^30A z(&$&oeXVt9sTrJOtFkE><2)VguYQMZek?qm*A6uK%@torNt6w!`4p{~&gzT69;m>- zj#P_%YwJM{ydQvD93JHQ1_@4!m?OeEYHAUC`fs$9g7`3;HPJF+Tft#%5_cu3H8wVO zJBu{6d8~!~h7Z*?rJ;gt4cesjOrL)6GE<_&qj8DCrzcHbwjkp|MxvX51?P`sJaW`d z`O?r4AoitLxb!qpJkV3GF??HJLy%BXMN~>GSh;OPngp@E^uqh4r~U;6D1pX|6HGa* zd7fc&qJ-_(g!wY2b(FJm{P`HzD$tWZ1s{+&uQ!beiSr<5$9HID_(@mLN=Su|{d33` zaKjas-F{J=3t`96`@?N}0&f;@f<6xaM4KzhqE*`?kzJtQ@7DPkBwGUJrNKbIP=VxEtjo z;3PEd57gh`>50B@u9BM)Vl%srX~ua*q&bl&JKCZ){GmNK$qUDYp66xl#*~_4&L9LW zASPfmpSV;cMOt5IAQX(%5Y*9 zrvylq1hnw7YNGYz(&yT6rRfUJeI;k38FHZ~Q|Kbik9-DftKhyZ#Tm(X(Pz@>W=d7v zce-5mTZt>qlLU*+9V^LKF=AruO|h74pJ=LcmWUc~ad{~;FW*Cc@rA3b1c!6mBfg{K z)6|T0zcq~j%coK-uT|GdRMNI)(_IR9kjGuKD)STImJ}{OrwAU!$4D(TtF?c$$F*rb zpjr=WOT+g~5Ohv$j}>BCl-$GTp7eHb{5#kfSc4g?T?lJFcq7a*y++~sSl)856DX8`gyHS4)feeS*-dMso-p+ z-`oDj;~b+?(kLWPqc&cgsez{`FQI0^g4tVh-JM0djj3&-Gntie4i4$h*FgU=DiU^A zpA2&IX`|;ekdd^g+ihcQd7H(y>U6lfHQH(T^nO*Nt;SM$T=VhwQHz#@(^wVxbc0C1 zPevhA>>5wRzi?>RHX+DCkCEaBLt|Xr#`p6)kJ30hKfkVSe@3HyYJ?G(fl~6xtq>sx&YM83yqIVgjAyLngL(+A!^N?Z2_rMw zkt0&e!pc0peI**arC0Rn=3+sof^qGn&rb67Q2YgS#s5NAw>ix6`DH@Pquw$yT`cf^ z^E0b97@t!Ie9?kU^KcMkJ8O{Uw0 z$ONV|fOa}x+-}Kpab9sLNNo@xSq7jY3C~ZY%eayT|2@Gy&ZB9o2&0)_R7u-jVs%h; z{{WFUphCK#EDJMp6SkE@;j8VPEv~0QbRylpk5oeLArKWao=EXv^Mw5=>MEGB$m@3o zUmHVeV7vH{R$fr%|ALwSfjiTM`0SECNz6hH{;vukzY=)4ETd{Znk~)Xwlpp_k*b}s zN%=q|Oq)Wa1wB=>qz2DmgAVRJPfYU4PDFCr)y81?)ZQl~JwM}fFMAx9>=1sLS5wzq zu>I^#(ea;^iB_MBOKplPsrkuj-xG9FsOZ2z^*Fhy^Q$1a)Rc+kDV&3yaTj z@w|Lq=LABJUh2HUdhf1UshxR2`Ft!N_bWh<&|MEZOk)p&SnpPQuiq9YvO6-dJ$tc}I=6}C$6&t(tb^;5^c7(m4$}JJithjwbgIaQRxpc4 zcJ~)1{rA$~*@FS)f33@|6C z5qvvolNm%Dh<`Je_7H1T7vz zy~uu_Lp88I0MUGmy4aSBabFpL;p{(h>I7QU;EFfYcw@xc%4+p~-*-(dKn;@DAyGCgXy<-qttn-t>J5Wi-hd#UZ!#Jte{ZNOiM&ndH8;-+a5uZ}vg= zS!i{Z--|ieQ~EcX0^}!+SJSizV_eZo>y-{o$sp2MWt7r{f*-lcRYeXxaXCQi{hVAI zA0eM@1%%jSL}aYIYx4CuEh(a6pO^H+A$x-E!Hf%{tnbB z1UaeK8_w;>sMB9aE?T2v>uHkf)Ky?4#Vn(~Q@B33-*eoNSbO)FvL?1h$M=2l+`z-y z1O^N1{?Ff6-Fsepvm)ziV_%=jSxebQzam@{Bji<*DS2QJ1hS#`K3%fnB4?3{;j|}F z5|T;wc#{H2e#y#fLj8|H;=}t%4irXxwuBl*5KQK3QoSGjeZ1YnxoKEgbDr8h<8xR} zmcZpZ|8h~;J=}VKS(lrf5H2NgKdbY>^7TT>t>FH=33nUZeUJIl&-=niWNqNjuGR81 z&07eAHd@c(35&Z)KuaFj;zgSq<5rLIe#6>*uko_q{i=30w`5{7Yz<565@|FN)1m9o z;*mb&h+-`HkVJCz(y8}j#at%-YBB(tc?CxVjNE@L+NBPrQ_(O1xj_G6o`q_BiA*8O zTP5y$4bvwe>Adn~^!rn==2e1NmOJtS_8Ys0ybZ4m;`0)ZOrBn-yp5MF(kOaqLTV2Dh zrH|jmk#?5z&UTkYe=t5`>Qe$*3?IA7QRYkIGwO|KXPrrd?Kw%Xxh0wM#($ju-+sjx zKWD|LyAn@TVA%bTdvs-iei;w+eE|Yp|GmH==Jj!c_LC&*R_ApyU`|;%kjr_NWysUP zek2~c-)!Z9oo===R1XufJT=)7L<92R!2!5(Zl(W)h|o}S)gQ|z1A+EdSQvqtt*A$8 zr_FQqC8Klxnzj-8^)%ucRBcrb*rx_*%k6H;gQE}ij z70w#HDQDy}MK4H|1AR}$xCbq!kILD&Flv)n^LhRUsC~fL$yoA*OQheJbpV^>s*$PK zx=cClh@kpz_@bQ3EmcIi`IS^5M=O?AD%95pHpeG~&SscZ1uzGl=s4b+!r+<*V(S zrhDaNbYXb+>W@u&>JIyf2 zG_*vDhadV-quGE;(2xTf#c|pY21gvk<*L&HbV3IrM~-S!TH*QNy~(DnYw^5*A<+}s z57FTeGg6O{T477JG<;%ANv3DKl+8%Rk1R~68j;IKI#7CO#~o#zfNo*#72juAg^9i> zP1++$qw#zI?+!${vknS+(b^Wmfwx1@yO+63aYr5Tl^Bd_<6sceC@hH3uo7@LZQ5a{ zm60geR~zA{C?}ohVIip>GZr}oK@m%lqIN?a4(=PP8i5jZrU3BA{X+Nt7Q}1M0ejbe z;dn~M74d%^elg7$qyXoZ*44-7jOPh_^O{j?_QY%9o?rv5OMyj<8zNfE4a%hU2%sPH zh3Eg*9l?e8=JA_r7!%T!YP{`K@2kQd5sIdD)I*>5kYO23FiG$kFY;rB;QF%=!>vQb z&AyR#@0t{%p)0tj0XVH+CrYjRQ5k2z!1kwnV-*t0Zq@xLbTlUQcid7GF&SmLJ=EDx z=TsSiN*7$#cJy||Y3iSzX=R{2Qmo@g&VI&{ZW0%aG8~=M3uwDm7h6pu#q=K1|Jdk$ zhmADR>N~vt*0HS!i07Z`PTd|IzpTlo5Zo-^7JAP9CY&hNNoZSWU#Bs+(}vt=_?Yuk zmEAw`Y5#4~eWw&M%N{6Pw*q+{WpIAjTzii>tQxrp0PNtElE;+PrYg_57-n=9c4c+m zgD}hWP`*7h0p}gS?hl$cjU%$x!@H}Ej-Hz`r?rn znn#kP+X5UwIW$33$DWo7U=LXcq; zU{|uvs@34W5iy9QdW3`CF~G(IpI$wG;~Z|kqKwTu$aSToM;UU^!0NK?bTFFW2cic> z*=^i;5G$JQ!QYpvizdgaifT^`dQXrTiU%!|Iej~8Vet>zd}>@wNDvz&$ZLvRd-w!p zZ)l20TQ%Etc=9$3Nu^B;+{xES_fcf`K8+5eacD*eqy=WRCO%qB&p)8#5NAMt zeVoHVLyjK7gx=JofC8|ClTU!$u!FxP5Ky4HQMw+Pe8a%B z+wSUo9c+Vghn(42uPV0Z-gDv>`#iGBn$9gd=hm|e1#y4b-ej~0-7>oMd(M0~LNGD#j8I+iOp|Cp-p_`<(<-dF;X%)V^UEF}|IIl1SJhP)B!K^|=O^U< z%}Ij$?YpF3`*G#}GelY2Ko3~kD;L&|(S@$-Bpi7a;xt80MIB_akIB?b+*<4pvk2V^ zD<&~LlIXv;98^a8KTy#nwLQ+>|obV-RSGHRv>ES=~9gsAy~J>v7V z!S_o|x3aELDv>3NPudJ)sO`$P8ph&Y*xRVDSG6k)Y;9|CaXTEnkFNX;P20N)wh*0W z<5x2zVDc4-BRNT1d5@I)AbbYT8`4;P#|b**#TOpwf!<`eBAM}IC5)5dn&1AkN`Hg? zU?$!44Tiv1IQXt`XjTj9KlUbFa3|MsHN6QLkH0>E-i3sU{I-FAUP(yPiMca;oe?A9 zqQEFZ;CJgAoi^_$m$`FdPEG;j<8<~=tod3Tqe|~?&gQb&>I6hm;)RVjuFXe{^e+v@ zxQ8$*>%V3JpLLNAN*p0yv50~Py4feJNt=?%423C+2T(Gigja%LsKL^(7#vl4Q_j(5 zz1Y;sdhjAB1#K%Ps{;fnk)C@gzky7UplY_F$`3={EPbXh<)jKoF$u`cA5yRh^gLSv zXQ_iNP=9G-O-|Ihx&iwVau;6O^`~|ox$FV_e|Di?BLo>uL^q50f$Gp6SjL7ykcc2u zg2KJ+UZSHJ|Hp4ZlN>Y7;3J;zChjsK>=yU0P3Bs6NnqH^i9y3>VJ4@M@^lkroc?>| zh8Olr9(Bbu{7a8(JDQ$CNs-@E!5*2oy8_Ed4@VMMRuuwaM1@cWnba){#Pf8>xIM9L z1fjggb@9$=&){D8G8tRpgBG|st=TVyT3Iq(YW}a3xH(26)7|oviRdE;TyreNqOjNe z&Onqi!Kr@bY(A|zVJg(o`fi>K28DUMbk3+F_I>rfS4R#fXvKpsg*EVuJ_CYmFLbO- z0X*QJ(YQV5!C`XzxL`}LJWFK^Qpe@`R+FBPFd1!u7)upj+G}u|eL#B*a|P~NIh97~ zG*0|F8zHD?Bg_e#) zWc7Zyw@|V@y&SR3UF0D$$sDU{{l}V%Ammi4b_TZ(bqV90*6siB7-R8vY`zG@F?b?P ztbzRf7mP%el81xnuJc(NEx?*R-syRUEwUC(&udL&0X-Qn4I`>@ZU-4%KOdKGH)xKe zCHPg$8IXm+ejU>>-8OK}8nS{}Vi+D9DRlh*kXML;k^VT{2n>{pmj`{yi?7brLU|w& z!Z;_e0d%!^5q=v!0xitQFAHZ{U8uTyUAp~&QVv54<5}lh!GBrQf$_v*li~%Fu`0+_l)+$^h77$o%k-t05KFJ( z7!l|<-pJdAQDQPw{q)zkdg&LV&nuVd+xQ}ABl7mwlpC5|^cJeqqC)u{HM{-DUAW>H z6$`XF4fWXX?8f5nDZUy0oa{J44g)G(n{p$DXrujDeC~WsY{&Lb5x}SMP}3JTbwv&l z4eS7|-p=`b)?wBvP#VPhS;+C>EVMHc)cY2EEup-y)Y@m4yfInM`gF^RwM8!wV{XF# z&|4bOGnYUMX762UQn+@pG+#Pwv&`nA*1QZO-iBt}ZwY>d4ioRu-MEU`hv5F>K|;{{ zeo|8Iah3hptp99j(&aNVV`-z&5*Zs8ri0NLUbKjHTD2jv6hd%|BH_I1*|;H~8kID> z(DJLT0OY)PY?)58xkG!JZAu|l2Cad6)*~wZDZE}6tDGTCLTTGx7~0|HDDWP7)U_4z zF(>dKjT&dN;Qv%)3>{0)unRzt=)B*;zbs(;?ij!b6|5SPI z?*V3&?7_0TsSapm3W6J{5%LSn02bWhv2BuiTzL>fuuj*Z6L;U7_jEG^khuC%SS0Dk z)tBAF?36xPg-Dk(nAhidO~Ix0yO?^%E2p0LgLpq18grHB^5VGv=CyosyyeT|YLH%I zqJkHiZFME^RT&pKOm&B7W&6o4oF*An!Q}>5{DEH9@AE7urz0!6+-#v^-OHl^dXSIl zjCl#1DU{ZzH}{X5(gpZ%qv>lPH{t51`Ti~5$O^{dSPeCZh*I8pYuM}#6AbSB5Ca?8 z|8RB~qrL#59X0-kD!hUPRLdw9iGt->1SA4{Z+R-`eSj8W_>2Y#yOUE5oLnVOSbNHM z@v7OvdLUw73!CM^I?_T!XwU}7sl6UaJ&~bTMe>YQ$(0Q6_uq2|DTnib>=G@VbrF(Xc6i*Q+s`D*o(O3joR$W&pr`|Z_W1lf#IFC2YI1djJdkKqHz8}&)?K93t%K}566O=ZQ8q_8x?;A`VmuA)DC=p`3nK%tc)90A_q0%B&3OO)Aq>!t-wrqsdQny^f zsEBdfqCwj@wX^4X=CB?uFV|H**w^w%0V9iV|AELLRegs-?cOj1#KL@wb%7e(0*&$` z57ffZzeKw&pPtCNrP|v+U$S?0`0TKBZV_Ymq}3Pqp%#fG0R+*0%wwPp(@=a@$c9D$ z?9?|LWoD%2VAkb#d;>dR5&;x?feJbJe@xMvnj)FnA&MaN6xwmLR)9awF4B{cdG?QY zDayOPc}9xA=^SyY3klXD;!fCOW~O4TrBGU)!!3}{drg05Twd%6d#LJHK$?*!rKxpc zM@KQGO&b*`4?Du|rH}I;qQ)$1t#>o#q#j%z`r|djmQA5gPdT83@6>g0uzDE^SLIy* zPTje~;FKgcI}m{zlx9yr&=bIv7L@x+SoOBI_I{d6#=)m(De%8WlvtPiVpahbV=prG zq(ToPZX{z$*DFF_f5NBCNT_=g1D+tsUl3ECGc538a*b8Z%Iqg?EJ#Uv;!D;D3}Rq} z3Cw3Eea0RDWWl?u1%a8P3M8wt9-w5(4fSkpS>+BqF$w{&0A){RSED4_b`9_77n>3- zB!*H~Kkco}b64b$5@|EmVM${v_`}vWaT>48k37JAfUV}rqKWmPJ8Bz`H`1U-&s|`h zeS2DWeXnf3VZjbQsg*6N&A#B2gQQRkj=VR~@sTUf=WF{bW#3VQqu#)U8F|+GfcCg7 z`a2xxkG)6(v(IU(1w<|owEorY>dgN%!q~6!ufgB~l5cTh3ruOk&-~-`;jx`BWO{xt zpxMp^N7m)nn}7|MW5~OmOLx5bbCOX_^^I*L9NdnSasWXw6Y=X9_mq!fpt|t>TAOsO zDuNi+F&IK*&RlYCn1R;Kfy#b7%B}5yEY>NH+gphi9kUtE{6arSdb_9ph2#miHkX)5 z(ha?Tvjwz(s~=y*aXa)%!{lY&7yG7w#i5K>sIN8NkLYNAoG^SC&t}yIF+XY|U-SI) zbKJ19veNr4`mV=z<|o{v?i{<-1E75_Izk4Mu^hHV7BsAKMJG?0a$}p*L#csuKbD~v zgn8hBKWt@pSCb49_GWn5(6PL5>EAj0Uw^0jQS5KV@nIf|W#HlB*`7t>+dPME4nfI+ zaM07v+e3+!?_gDoVxQR#JqYi@EmE%nclvhAU@m+{DV6eRND0>kOyqtb(y z3tIDG;g87y?&OYAUu(R?|3NeY`4>FzM+*p)4eYN}6)12?Cqn<-Tml>AkRU zPh3KPpZ9MT^>1kwplnS4hj1+z0gnG8TGi18d13VL>S%!&1^qvRQXF`oK0GfWzHt5j z>kXO&cvpRBg{J72WgQ=6j|t1kOi^r8_QEkpL(t_id0O7i8lc6+#F7FZN%w{h5$!Av z(uNx;r4)2|HF-cN>d1Rn0ZT(4t_~l13Fg#rd6kpx&fReQxEO(dFg%`Phymx-VgR&1 zQR#;OecRV7mO@ll$i%F1#`O;E#TA-)@8lk135O$+BCqFmcZQrV9(JU9Nsbd-?!>C5XZ-&T7R~N@{2f}=odh(xommPqfrnN}Cd?FeI9+F;tcOjR6K_G$x3TG2>1 zWK`YSU4x;CRrx*5EEo{Hu;BUn$`6ofpCVcq^~FPnh)kio)HU`cxVI^GB1a14Y zyfLb?eejsuB;@220-p|Kcf_1wxVhkh>w^fb$M9HgSi7QGeU?eBnX$w@g#FUVWf?vX zOEZrP#8q%Rdlovgt7=7$%!cKjT7r5`Q{9nIw|+g#&Z}I4lE$)zbbkV&hL^Zw*kzr) zt68bf>C!l~enzRBsDvNEFfQb;?pckL)m-VI!dPh@O~Wb=yYCw* zP7(ix@*6G5uz-Z|Me1>|!?EogqEj1_P0Pcd{{qYD*%fj&C$O|eN3(P2B_wvc+m|-W zuq90_J2O*S(l)xhQbVn3LMv=}jk~#)56QHtNr6{eItQZ7)6Ae9 zEl8r+q|)9_0{UV z^D_arxd)9!8MU1hoIwb;tZz;p9a8kINyK#UcjNsmmbi90ye~F40G_Pn(L_2v4V>R! z`sQ`;2g?=%wBK@#)xLMR#;Q&{jN%fE&HbIBmrTc_f+=4#x975q*gve8*$C%tqY7p$ z{ue7UcNpb3!wDkGhR?{l7>f?H7c~j=5p-vcA|b zCm(k%o=^+@KJob&1`F(SAx8IxAZrbc!)zn(FWtLL1sH#TP|DM8tS#2TNN*33B@_&} z*4$DI-o1Tw)wWLro9KvFv^F@9hQ8j#>q7xRY-}W#8b>=%ZGmI^FpeR$x~;60WWhJe z1ybUh+~;<#azjMHXd$G-3y61v#0uAqapV5bFKJ3z~R=6a?O{iwO(3UFg+IBe@vvvfdxSGo|wK?8e>FD zF1>Phwm^H=G89ybPc=G;2dY=r4mmgMPGmE%A9(N%F8GusBLYk4tc6EVBTKa$19E~z zu%Eu#X=vIv3h(Dv2jlb^2WMlf)Q#TdaB=Drlb>VOYo9}UfUuIPeKrNfQ+VgYv5?lN z2zDH8g{AdxwOYzt3?$d3N}vBC!WHoq=)d(0x^EoX_Hta@FdHwKH6&FwEn|rntsd?* z!ERhjeM2q#+*DFi{}UTnLCgImHlT{8a1D-)RxAoZ`mfC<5jCy8Aeh z^E$wY)I!66g4<0m`ARMcxVA^3pcqUY^mY)k#)X@EcK*UPi{IE*(Xu4hcb-MGBkN#d z;FX3oLWEmCE3!pPJpn$NHu%x~+9BQyd&bIcy%} zGrkAbsgGguo!iYII=zIqz5T0xe?O1>_Ub0?KrB#pl_Zhf#Cl#BZ>)RQkyFJe&Idjz z$~~atipCgomo3Rv$5^Vyp;MH~lPEHqDIIwvpO*c)JTa=L(R8a0cMk)*Q===Nk4@;SL zE}3PzVPxw1>EKBflJT64qPIKnl{Kx&6jP{uTl@kDF zk*j^@kypZod@9YNb(&&Y=+7u0w>ZfkSdoO>+NQZ;JSSuR#A-!MoX2nk+SQ^zd@V|` zoecCq?q(nX*)Sy~v9bi6<{$AQZo-~02E0Jc{7$i zDaN!jK@~O%Z5wT}8JJM<{&S2T@sQ;C7Bgp(J=Z*pQ0&5Oki6sNB zM$qY;3O}v&!YWXQlGj=fQ8g1lek`)D^MsmNk_Txm_;3mkO-6~cZ5Q6qCppNUjSH-( zxY<;b@1VdXCDyK^W0l64l_o7GiOWeVBEfoAVPR zY$e#3pkx?51Woj}2m0_rh#=Sm4k>FXRTN*k#E{n)wGOF zy7AJ3i-KmVZ)_uRWw5V=>l=twoI}UBxnKmF)P_%UX2PYa7_d{#u;aJyuC_Mw-WH&S z)@w06c<_oc!>3Xr%#at4q6^pc$uvgucxuQ@{u0zoQq?652N2Qc2`%?IM7s63AN!zf z`lb|8^jOmVP{}tT%((+jcDgiE5iePGyZ(qsiY#0BT_Jcw7vIp>_;e)dc=_}LDv$Kh z?9(HT_c1_BxN_=*E<5=mG%hn3z1$R5UkhHvQwG~xPdmq1>{B#_Y_gm4uH3?>>gY?= zIc>ZwrYeCd_Q0p>@TGs%HxuoFjh^ZZV03l9)@jbd*nL^1Tw5`gbL+icBS$t$f*xf9XnO zJYxzgh5A8Hg+PXdxWhy#RQ4YaK}&`ob{A1>T(59na%xE{d0;`3y zI!`4drRzc)>DrI{_p*DFN{G_`aEMnZ!oxR=0^K|g#Js&u^qlPa4(^B zw|*!>(ENJYP1O4HsrpOCD80Ly9XU z*WUC&CiOYL4JswbA3rx5ueMN-V8qGYDFD?v!063uIXWIbZ^B$|$%ga_Z=2(3O zi|9Y`)_C~F&f4EjoWG&sYuo9JmXSF%9Fog4;9PMAp-z+r{ z1B)1w&hChrXAI6I_$9d2ff5G14P*CUH0xGKaeE`{$6>iStDYnfU@jYtcwJjQF9R-@ z4vnaKwqElASaj=K^Wky60ZCe~r#@k&%t_$2)aTAM|7IKwr!3GW#MAd$)iGqe0rcZpHdWaqf2*m-1_NuJaKdLl9x2>?4SOTig-UB ztLGougLh3O^9#B^Ja@yyr1Q5adTx^R#akD$yXeE1i#GQ1 z9f6@S%Bz(5+K6^qMbNI$Y}6Y;CUe4^$OFy&vNPX<8F&2RtlgHL=Em}L)NB7Y>?a<0rF&ka5(~V*_i~p z6@*yfB%*B3{l4rvRZJmCZ1B)~+-os7i^W6W>?Kqs{gnW|NpD5t3G6P);5Q784#KzEjeVgIXdN4icNO)-}$pIB;XSKCc`l6U@ z#}!EU7N*qDL#P_ZVg#0tEVrXPrGkH_RC4!QU6k6}0-J>wx?}rB;8xOa$+ffkkzo z8dV&TnI|wV2ZOHTF^c)B_FR{W#DLyHhpad}h^^^I%b9%MQq!C#3YJ+p&c1mw%aOq} z3n;8YQ3lm15Yw4?PH6^!9&A{J%@I1wQdr!P5QsY{c<5m}6aFw?iCHk-%h^BJjv;AL z-aGdk1rcnFW#{%~Lw4y<347LnKksCPi2g1nMLi;trH_e4lxDNo_w=1}%L!nq+`^@b z7p}NJ$D9SV6w8EhL#p(-17ysGTfy->|K8R{pChb67IW?2b?gN1HNyl1_Yp$^vn{A; zI3Py2!vi<)oOZA4K2Gf`{#A}mGmOJhT*pP(HwsN0nKX1gnCN7f;Z{}$r;q$nld)v- zhL_m+cv8&Yd%J7k=hm-h19E5}jUpsouZ7HvF1h7GnO?bo^>_qlCDupsP!FFIY|*%0<+Y3$oBKKXC4%KiLZ7?E>Y_ zgl=~`WzIbfF^n<0jVOvYohV=YSs{)$-naG5T>iOG9Q1@XbelZdKr02H?#`5pe{PJf z6}N@O@17u(D4VpNL#*Rm-}(i5QZCJBcKc6fo!{F_4Vv$=^9u6166>{e9KQtP@thfH zJC4-yy=6o5=Qo~4t5`CUN8(PV;H^b_wd!xrv%^#%|0$HI!2~flCR~^5A*%fM(eu{{ z|Ai2tjiKP9?0VoFbc2$aB1OMgx zf?9TO_k@hl+P^)K?gMb&6iwHpUKB1}geDHO?vuen*#ojlge(PFn8SMn{A*bGs| z?|}gD8TZn2ynLC0{nSHuh>9jKHna@0qgq3=>*#8d(VdsjM!ep=wS-O~&@W(g)12h8 z8cOcmzR%4Y9D$azZ5G~IMoU|};SphCpZ?xb@nC$Hu?p&cA~A}nnj~M+0UNb{!l+5F z+DU1edh3;vVj)O|i7^vc%542ZW(B3nzJcwuj_Lx}pEH^jw5(&Snldf*p4T8-Y zMl&*~a(kePwl3S~n{Hp=4%b|Dd(p}lN8M3N8miyncgor`ZS&^l$<*`sj1Tp_!tm~R*IK)&D}6S(+?7Xi$T=4bIjar6go5Pw9srZNf z4N!#qpbXn%o`Jg2FVasJA}9hgw@CBllD&V28c3CWHw}kwj!#`QijLB5g&AiR{aDQ; zF9wE4P8#^`M5acv1&d$iz@_Y_+G1i5;gMTvxFp9Owv;s_D5)^3&q9LJVbEEvc`Y*4 z6YkoB6Uab4f`eHMXC*yH){4@04CHW|5gO zDiZTO`unyk7rUg#VAHYAEAF_o&ovQ=IvS~M?`rlH$77}H>03=G5_i^8VV1_Z_Jg0~ zz#fPecxzBBpebF5^g*<`nH`#{1O`PA{J`WRUXSr^}_0b|I*~Pkj!wl}B^|+Xz zuQ=k?6ulTX$L2|iKIn=EuK#@waeV|a;0SW^nG`04>7YNEy}W63Q%g}kf*)f6*YHHA z-zKn4F$7gT3V*YBBMJfz%H|Iz=>Tg{H*%X@dNX|;OCcWfTTzr`DNb;IV6YK5V;Dq!fU?gM)~I*ieA(ND&@e+jAI zB6hpoBwg4(%BvY8w0JpOgL_atwe=JL@1BIhwMPd(GhD1CcS#%180EGh_t{CeVWV%J zCb~%JGL0^RfQo@Gy83$NxSz5Md&=z=y;9~u5>oBbQHGwAoH){4G2uzvBSF9eulkxd z+$l@w4f4i{6l-M&!CMWM!)%A;NheFQ-+K1s8%zt=!a?*k?dFm{hslc<&g<@0@0O#X zH{~}%f2Fc8W^R__)_S3fSx!l;1eKy*fr~H2mI|@_n&i4IX98@GC=%#RzxL1fZr??C z3NfPBy)|%=^Oa48ZFrm^)>CoF_}Wc<$96lUuf$}SYr{Eh?o$`aFd_S_NH~ftFAqsL zuGdw(v%*J1-!4r^^61Zbm{osnPB9v04w2m-p3ehDOQ~2Gh5ePJxsXOQJsZ~HShQ|s zrfPRrAdMn-$uR?sc)?GT=i5PyA8VyFZ`_I?x%DcP3OE5NEuAoEEtw3`#A$KQWc`jNY zev?T?7o0Eo4y7mFwBQeqUNzY(wL{$$mpp%>|M4h>AB^|Z2`|tKiS`&&B1^mQ$=`ok zwe)@-$7daIs$}lq7V7L?<$268HTNk?=5pCIo8kD@l~*EDO_vB3KgYCJbOE`+C+_J< zS)8c%y?RjzX#Vyyt#e_m29t#U|Z*0bRNA|60d=<(iM4W4mH`}QebLUBfx zmKONfOM-(=)b=>JSn~AodG{CxfHh}#s)sgHh)4ajjAM`z>`7)D1|6&Rx0lC-@$oCO zSZH!CVcI3%+xVQkPE3FX0PjvCNx$%%8_f+AfNf#JGmT60N%uOxknZJ{zqZXRA`|6h z1DN}|{lOOW*~I)xVmd}!)~N5++i6zvxoBR_CRbcqeHdQcP(r%93gt0q>S$nGA&1^! zeAb#7GvWH{kNDj}{cDkwCb!U5ilc5nojxfld^CS=cf940VlQH3n2!@xixz=QcXEOfdA#aFR2 zj#LY}Vh)8K$$9D~Xp0NhYH7Y+4(G64UumO@uhSPoVaJ0uHWzghI1nXtIml!=xpkzN z^A}}%KYOEAG>E6l9~VV)Q@%^IRh}OFQn{gP@hA<8V$H6c#J}P-r;PMc?Z@XAe7}7{ zf=jM>!W8giEFNv9hqCeF+U_l1gS}iXy$=P#MtV;I#3^O`%H#$Ibqji;)66t?S~gh? zkCPZiIbS@&Dwv>H+?=H6BRnoT2?u^V$g*Kl+WT6TKruZVJ7&k&d+dk&b(a<}vYX)6 z7QHw&=VPcGSb7VvyDFTm6&*h;Ak=pt;88y)z%eph=(Z6{Do_CksFDCr`WqWia;Azm z%*^9;Sq{BPzLkdVmeK=h^8oz;z@$a2MIBFvs24+H+B0Li7THps^p zzX0}%e0)-8Bj>SPamGOs#*HQmv+MAix$WaP5BD$*{05m4N35!!c{8DU=0GbWnyHeF zTM;*e{djRS%k@69ZNAok2!fyYtQaNKtI|&sO5YKtdErdxYYsvJCl&<=@+Qbiij)UotMi51-j`CZs4UU-7s0^ zvim06X0@)QlGT>Yi^a1txwVq?TqGCd0wK$!1=NEkGO<&{w|8-xX_24Q;&csFDB_cz z&UY7(ZP{hvg)-?|s)j;NNwk~Qd^QD?K^ivA`I|4kN)zfSilIaCo}(s34ek~pOf#kK zu6U0iV*cQILWcf{A)9)OCz;pS$3Kt{$ zUd=MXF3X$sPR$08n&dTTa>M6j>l_(UCI@vJ#Z6vR=RijJ`mqfSkY{%hhzELX8tzY( z#zYU497Er?z&aq;A!pHk{jn>0SJW+}TYteSyEWMBjdCW{2X{w<2tj!Tn)m12g#sZm z2PZo4Z*_05w_g^mi91m=w<6PQ{HSK?1hF;w3e_R90pp@<&X$5g3sm=o%qdGaF3N4Na zTCotiezn1sIhX4G+WJK_D5*bpM8rWZ);D=-tNW8BPLx{Q55~w5Ac0+6BD{90=J|{M z&~1?RZ{*nXccq|ODY1`jiwwaD-lgP}()pj+Pvok1J^d(B(R_-(=J46fw|o3OY{Mk znHKHtSr;+KIlr&2=BmF+aL&q?~97vc*pTIUV6fDiXWXgI2)$wYEAvHF_R(Ws^ps4s0^dg`5 zy&uSwNwElE(>o#}&4UNn{R`vGJp k6A3fT`W#CWw2a^YIB5(nN%Zxn%~{OPnzP| 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≻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 Editors > Colors & Fonts > Elixir setting name in comments above each paragraph +defmodule ModuleAttributes do + # `@moduledoc` - Documention Module Attributes + # `@moduledoc` heredoc - Documention Text + @moduledoc """ + String Heredocs are highlighted as Documentation Text + """ + + # `@doc` - Documentation Module Attributes + # `@doc` string - Documentation Text + # `@callback` - Module Attributes + # `callback_name` - Specification + # `atom` - Type + @doc "A callback" + @callback callback_name(atom) :: {:ok, atom} | :error + + # `@macrocallback` - Module Attributes + # `macro_callback_name` - Spcification + # `list`, `tuple` - Type + @macrocallback macro_callback_name(list) :: tuple + + # Types + + # `@typedoc` - Documentation Module Attributes + # `@typedoc` string - Documentation Text + # `@opaque` - Module Attributes + # `opaque_type` - Type + @typedoc "Don't think about how this works" + @opaque opaque_type :: [1, 2] + + # `@type` - Module Attributes + # `type_with_parameters` - Type + # `a`, `b` - Type Parameter + @type type_with_parameters(a, b) :: {a, b} + + @type type_name :: {:ok, list} + + # `@spec` - Module Attributes + # `do_it` - Specificaton + # `any` - Type + @spec do_it({:ok, any}) :: :ok + def do_it({:ok, _}), do: :ok + + # `@spec` - Module Attributes + # `do_nothing` - Specification + # `result` - Type Parameter + # `any` - Type + @spec do_nothing(result) :: result when result: {:error, any} + def do_nothing(result = {:error, _}), do: result +end