From 4c629840bdb84df1d989d915885803c11c9c32f6 Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Thu, 23 May 2024 15:32:14 -0700 Subject: [PATCH 1/5] Changes SExpression children to use `SEXPRESSION_ATOM` instead of `VALUE` * Adds changes in `IonSExpressionBlock` to consider `SEXPRESSION_ATOM` as children as per BNF grammar * Adds changes in `IonCodeBlockSpacing` to correctly consider `SEXPRESSION_ATOM` as children as per BNF grammar --- .../plugin/intellij/formatting/blocks/IonSExpressionBlock.kt | 2 +- .../plugin/intellij/formatting/blocks/IonSExpressionBlock.kt | 2 +- .../plugin/intellij/formatting/blocks/IonSExpressionBlock.kt | 2 +- .../plugin/intellij/formatting/blocks/IonSExpressionBlock.kt | 2 +- .../plugin/intellij/formatting/blocks/IonSExpressionBlock.kt | 2 +- .../plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index c7e1c91..7aeff8d 100644 --- a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -20,7 +20,7 @@ class IonSExpressionBlock( ) : AbstractIonBlock(node, formatting = formatting, options = options) { override val childIndentedTypes: Set = setOf( - IonTypes.VALUE, + IonTypes.SEXPRESSION_ATOM, IonTypes.COMMENT ) diff --git a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 12d64d3..ac0223e 100644 --- a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -20,7 +20,7 @@ class IonSExpressionBlock( ) : AbstractIonBlock(node, formatting = formatting, options = options) { override val childIndentedTypes: Set = setOf( - IonTypes.VALUE, + IonTypes.SEXPRESSION_ATOM, IonTypes.COMMENT ) diff --git a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 12d64d3..ac0223e 100644 --- a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -20,7 +20,7 @@ class IonSExpressionBlock( ) : AbstractIonBlock(node, formatting = formatting, options = options) { override val childIndentedTypes: Set = setOf( - IonTypes.VALUE, + IonTypes.SEXPRESSION_ATOM, IonTypes.COMMENT ) diff --git a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 12d64d3..ac0223e 100644 --- a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -20,7 +20,7 @@ class IonSExpressionBlock( ) : AbstractIonBlock(node, formatting = formatting, options = options) { override val childIndentedTypes: Set = setOf( - IonTypes.VALUE, + IonTypes.SEXPRESSION_ATOM, IonTypes.COMMENT ) diff --git a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 12d64d3..ac0223e 100644 --- a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -20,7 +20,7 @@ class IonSExpressionBlock( ) : AbstractIonBlock(node, formatting = formatting, options = options) { override val childIndentedTypes: Set = setOf( - IonTypes.VALUE, + IonTypes.SEXPRESSION_ATOM, IonTypes.COMMENT ) diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt index 49f9e9f..5b96cc6 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt @@ -97,7 +97,7 @@ private fun createSpaceBuilder(settings: CodeStyleSettings) = before(IonTypes.SEXPRESSION_OPERATOR).none() before(IonTypes.RPAREN).lineBreakInCode() - beforeInside(IonTypes.VALUE, IonTypes.SEXPRESSION).lineBreakInCode() + beforeInside(IonTypes.SEXPRESSION_ATOM, IonTypes.SEXPRESSION).lineBreakInCode() /** * Separator spacing, by default no space before and one space after separator, like JSON. From 478be38e1350a6aa29c4c4c9454d79834ff57350 Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Thu, 23 May 2024 15:32:46 -0700 Subject: [PATCH 2/5] Adds changes in tests for usign correct node names --- .../intellij/parser/IonBasicParsingTest.kt | 62 ++++++++++--------- .../intellij/parser/IonPartialParsingTest.kt | 19 +++--- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt index 89cc0ee..b2c21e4 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt @@ -67,7 +67,7 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { IonListImpl(LIST) PsiElement(LBRACKET)('[') PsiWhiteSpace(' ') - IonElementsImpl(ELEMENTS) + IonListElementsImpl(LIST_ELEMENTS) IonValueImpl(VALUE) IonSymbolImpl(SYMBOL) PsiElement(IDENTIFIER)('key') @@ -87,7 +87,7 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { IonListImpl(LIST) PsiElement(LBRACKET)('[') PsiWhiteSpace(' ') - IonElementsImpl(ELEMENTS) + IonListElementsImpl(LIST_ELEMENTS) IonValueImpl(VALUE) IonSymbolImpl(SYMBOL) PsiElement(IDENTIFIER)('key') @@ -107,28 +107,31 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { IonContainerImpl(CONTAINER) IonSexpressionImpl(SEXPRESSION) PsiElement(LPAREN)('(') - IonAtomsImpl(ATOMS) - IonValueImpl(VALUE) - IonStringImpl(STRING) - IonQqStringImpl(QQ_STRING) - PsiElement(QQ_START)('"') - PsiElement(QQ_VALUE)('first') - PsiElement(QQ_END)('"') + IonSexpressionElementsImpl(SEXPRESSION_ELEMENTS) + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonStringImpl(STRING) + IonQqStringImpl(QQ_STRING) + PsiElement(QQ_START)('"') + PsiElement(QQ_VALUE)('first') + PsiElement(QQ_END)('"') PsiWhiteSpace(' ') - IonValueImpl(VALUE) - IonStringImpl(STRING) - IonQqStringImpl(QQ_STRING) - PsiElement(QQ_START)('"') - PsiElement(QQ_VALUE)('second') - PsiElement(QQ_END)('"') + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonStringImpl(STRING) + IonQqStringImpl(QQ_STRING) + PsiElement(QQ_START)('"') + PsiElement(QQ_VALUE)('second') + PsiElement(QQ_END)('"') PsiWhiteSpace(' ') - IonValueImpl(VALUE) - IonContainerImpl(CONTAINER) - IonStructImpl(STRUCT) - PsiElement(LBRACE)('{') - IonMembersImpl(MEMBERS) - - PsiElement(RBRACE)('}') + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonContainerImpl(CONTAINER) + IonStructImpl(STRUCT) + PsiElement(LBRACE)('{') + IonMembersImpl(MEMBERS) + + PsiElement(RBRACE)('}') PsiElement(RPAREN)(')') """ ) @@ -143,14 +146,15 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { IonContainerImpl(CONTAINER) IonSexpressionImpl(SEXPRESSION) PsiElement(LPAREN)('(') - IonSexpressionOperatorImpl(SEXPRESSION_OPERATOR) - IonSymbolImpl(SYMBOL) - PsiElement(IDENTIFIER)('test') - PsiWhiteSpace(' ') - IonAtomsImpl(ATOMS) - IonValueImpl(VALUE) + IonSexpressionElementsImpl(SEXPRESSION_ELEMENTS) + IonSexpressionOperatorImpl(SEXPRESSION_OPERATOR) IonSymbolImpl(SYMBOL) - PsiElement(IDENTIFIER)('element') + PsiElement(IDENTIFIER)('test') + PsiWhiteSpace(' ') + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonSymbolImpl(SYMBOL) + PsiElement(IDENTIFIER)('element') PsiElement(RPAREN)(')') """ ) diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonPartialParsingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonPartialParsingTest.kt index 191cdae..e040606 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonPartialParsingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonPartialParsingTest.kt @@ -13,7 +13,7 @@ class IonPartialParsingTest : IonParserTestCaseBase(dataPath = "partial") { IonListImpl(LIST) PsiElement(LBRACKET)('[') PsiWhiteSpace(' ') - IonElementsImpl(ELEMENTS) + IonListElementsImpl(LIST_ELEMENTS) IonValueImpl(VALUE) IonSymbolImpl(SYMBOL) PsiElement(IDENTIFIER)('element') @@ -75,14 +75,15 @@ class IonPartialParsingTest : IonParserTestCaseBase(dataPath = "partial") { IonSexpressionImpl(SEXPRESSION) PsiElement(LPAREN)('(') PsiWhiteSpace(' ') - IonAtomsImpl(ATOMS) - IonValueImpl(VALUE) - IonBlobImpl(BLOB) - PsiElement(LOB_START)('{{') - PsiWhiteSpace(' ') - PsiElement(BAD_CHARACTER)('abcde_not_valid_base64') - PsiWhiteSpace(' ') - PsiElement(LOB_END)('}}') + IonSexpressionElementsImpl(SEXPRESSION_ELEMENTS) + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonBlobImpl(BLOB) + PsiElement(LOB_START)('{{') + PsiWhiteSpace(' ') + PsiElement(BAD_CHARACTER)('abcde_not_valid_base64') + PsiWhiteSpace(' ') + PsiElement(LOB_END)('}}') PsiWhiteSpace(' ') PsiElement(RPAREN)(')') """ From f0b4f528a99bcd47d04b23c589d3ccf398489c0b Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Thu, 23 May 2024 15:33:12 -0700 Subject: [PATCH 3/5] Adds changes for PR workflow to run Gradle Build task --- .github/workflows/pr.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7922b4d..5c6e581 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -81,6 +81,10 @@ jobs: echo "::set-output name=name::$NAME" echo "::set-output name=artifact::$ARTIFACT" + # Build artifact using build Gradle task + - name: Build + run: ./gradlew build + # Build artifact using buildPlugin Gradle task - name: Build Plugin run: ./gradlew buildPlugin From c489a4ed70fb6807c4ad3407efc1240caf2cb23e Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Thu, 23 May 2024 16:12:24 -0700 Subject: [PATCH 4/5] Removes treating first element as operator in SExp * Removed operator definition and usage in SExp from grammar * All the code in gen/ is generated from IDE `generate parser` based on BNF grmmar * Removed all reference of sexpression operator * Modified test to format first element as a normal sexpression element --- .../formatting/blocks/IonSExpressionBlock.kt | 33 ---------- .../formatting/blocks/IonSExpressionBlock.kt | 33 ---------- .../formatting/blocks/IonSExpressionBlock.kt | 33 ---------- .../formatting/blocks/IonSExpressionBlock.kt | 33 ---------- .../formatting/blocks/IonSExpressionBlock.kt | 33 ---------- .../amazon/ion/plugin/intellij/IonParser.java | 66 +------------------ .../ion/plugin/intellij/psi/IonKey.java | 5 +- .../intellij/psi/IonSexpressionElements.java | 3 - .../intellij/psi/IonSexpressionOperator.java | 16 ----- .../ion/plugin/intellij/psi/IonTypes.java | 4 -- .../ion/plugin/intellij/psi/IonValue.java | 5 +- .../ion/plugin/intellij/psi/IonVisitor.java | 4 -- .../plugin/intellij/psi/impl/IonKeyImpl.java | 6 ++ .../psi/impl/IonSexpressionElementsImpl.java | 6 -- .../psi/impl/IonSexpressionOperatorImpl.java | 42 ------------ .../intellij/psi/impl/IonValueImpl.java | 6 ++ .../com/amazon/ion/plugin/intellij/Ion.bnf | 3 +- .../breadcrumb/IonBreadcrumbsInfoProvider.kt | 3 +- .../formatting/IonCodeBlockSpacingProvider.kt | 1 - .../intellij/highlight/IonSyntaxHighlight.kt | 2 - .../annotations/BasicIonAnnotator.kt | 5 -- .../markers/JavaIonOperatorMarkerProvider.kt | 39 ----------- .../structure/IonStructureViewElement.kt | 1 - .../plugin/intellij/utils/IonSearchUtils.kt | 14 ---- .../formatting/IonBasicFormattingTest.kt | 12 ++-- .../intellij/parser/IonBasicParsingTest.kt | 23 ------- 26 files changed, 29 insertions(+), 402 deletions(-) delete mode 100644 src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java delete mode 100644 src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java delete mode 100644 src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt diff --git a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 7aeff8d..596ce89 100644 --- a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,37 +32,4 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) - - override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = - buildSpecialCaseChildBlockFormatting(child) ?: - super.buildChildBlockFormatting(child) - - private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { - - // Lazy evaluate the previous sibling if needed. - val previous by lazy { child.previousSibling() } - - /** - * Check if we are the first comment within the expression, there is a special comment - * case where we don't want to apply the child alignment to the comment. For example: - * - * (join // special case comment which is inline with operator - * // child comments are inline with inner values - * anotherValue - * ) - */ - if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { - - logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } - - val comment = child.psi - val expressionOperator = previous!! - - if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { - return IonBlockFormatting.sameAlignment(this) - } - } - - return null - } } diff --git a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index ac0223e..1b138e1 100644 --- a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,37 +32,4 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) - - override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = - buildSpecialCaseChildBlockFormatting(child) ?: - super.buildChildBlockFormatting(child) - - private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { - - // Lazy evaluate the previous sibling if needed. - val previous by lazy { child.previousSibling() } - - /** - * Check if we are the first comment within the expression, there is a special comment - * case where we don't want to apply the child alignment to the comment. For example: - * - * (join // special case comment which is inline with operator - * // child comments are inline with inner values - * anotherValue - * ) - */ - if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { - - logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } - - val comment = child.psi - val expressionOperator = previous!! - - if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { - return IonBlockFormatting.sameAlignment(this) - } - } - - return null - } } diff --git a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index ac0223e..1b138e1 100644 --- a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,37 +32,4 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) - - override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = - buildSpecialCaseChildBlockFormatting(child) ?: - super.buildChildBlockFormatting(child) - - private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { - - // Lazy evaluate the previous sibling if needed. - val previous by lazy { child.previousSibling() } - - /** - * Check if we are the first comment within the expression, there is a special comment - * case where we don't want to apply the child alignment to the comment. For example: - * - * (join // special case comment which is inline with operator - * // child comments are inline with inner values - * anotherValue - * ) - */ - if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { - - logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } - - val comment = child.psi - val expressionOperator = previous!! - - if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { - return IonBlockFormatting.sameAlignment(this) - } - } - - return null - } } diff --git a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index ac0223e..1b138e1 100644 --- a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,37 +32,4 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) - - override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = - buildSpecialCaseChildBlockFormatting(child) ?: - super.buildChildBlockFormatting(child) - - private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { - - // Lazy evaluate the previous sibling if needed. - val previous by lazy { child.previousSibling() } - - /** - * Check if we are the first comment within the expression, there is a special comment - * case where we don't want to apply the child alignment to the comment. For example: - * - * (join // special case comment which is inline with operator - * // child comments are inline with inner values - * anotherValue - * ) - */ - if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { - - logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } - - val comment = child.psi - val expressionOperator = previous!! - - if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { - return IonBlockFormatting.sameAlignment(this) - } - } - - return null - } } diff --git a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index ac0223e..1b138e1 100644 --- a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,37 +32,4 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) - - override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = - buildSpecialCaseChildBlockFormatting(child) ?: - super.buildChildBlockFormatting(child) - - private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { - - // Lazy evaluate the previous sibling if needed. - val previous by lazy { child.previousSibling() } - - /** - * Check if we are the first comment within the expression, there is a special comment - * case where we don't want to apply the child alignment to the comment. For example: - * - * (join // special case comment which is inline with operator - * // child comments are inline with inner values - * anotherValue - * ) - */ - if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { - - logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } - - val comment = child.psi - val expressionOperator = previous!! - - if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { - return IonBlockFormatting.sameAlignment(this) - } - } - - return null - } } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java b/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java index 0d48577..27486a6 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java @@ -472,79 +472,19 @@ public static boolean sexpression_atom(PsiBuilder b, int l) { } /* ********************************************************** */ - // [sexpression_operator] atoms* + // atoms* public static boolean sexpression_elements(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "sexpression_elements")) return false; - boolean r; Marker m = enter_section_(b, l, _NONE_, SEXPRESSION_ELEMENTS, ""); - r = sexpression_elements_0(b, l + 1); - r = r && sexpression_elements_1(b, l + 1); - exit_section_(b, l, m, r, false, null); - return r; - } - - // [sexpression_operator] - private static boolean sexpression_elements_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_elements_0")) return false; - sexpression_operator(b, l + 1); - return true; - } - - // atoms* - private static boolean sexpression_elements_1(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_elements_1")) return false; while (true) { int c = current_position_(b); if (!atoms(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "sexpression_elements_1", c)) break; - } - return true; - } - - /* ********************************************************** */ - // (annotation)* (symbol) - public static boolean sexpression_operator(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_operator")) return false; - if (!nextTokenIs(b, "", IDENTIFIER, Q_START)) return false; - boolean r; - Marker m = enter_section_(b, l, _NONE_, SEXPRESSION_OPERATOR, ""); - r = sexpression_operator_0(b, l + 1); - r = r && sexpression_operator_1(b, l + 1); - exit_section_(b, l, m, r, false, null); - return r; - } - - // (annotation)* - private static boolean sexpression_operator_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_operator_0")) return false; - while (true) { - int c = current_position_(b); - if (!sexpression_operator_0_0(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "sexpression_operator_0", c)) break; + if (!empty_element_parsed_guard_(b, "sexpression_elements", c)) break; } + exit_section_(b, l, m, true, false, null); return true; } - // (annotation) - private static boolean sexpression_operator_0_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_operator_0_0")) return false; - boolean r; - Marker m = enter_section_(b); - r = annotation(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // (symbol) - private static boolean sexpression_operator_1(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "sexpression_operator_1")) return false; - boolean r; - Marker m = enter_section_(b); - r = symbol(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - /* ********************************************************** */ // qqq_string | qq_string public static boolean string(PsiBuilder b, int l) { diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java index 0bfca54..af18df1 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java @@ -7,8 +7,7 @@ public interface IonKey extends PsiElement { - //WARNING: getKeyName(...) is skipped - //matching getKeyName(IonKey, ...) - //methods are not found in IonPsiUtil + @Nullable + String getKeyName(); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java index 6d5e700..1218fc1 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java @@ -10,7 +10,4 @@ public interface IonSexpressionElements extends PsiElement { @NotNull List getSexpressionAtomList(); - @Nullable - IonSexpressionOperator getSexpressionOperator(); - } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java deleted file mode 100644 index 1845304..0000000 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java +++ /dev/null @@ -1,16 +0,0 @@ -// This is a generated file. Not intended for manual editing. -package com.amazon.ion.plugin.intellij.psi; - -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElement; - -public interface IonSexpressionOperator extends PsiElement { - - @NotNull - List getAnnotationList(); - - @NotNull - IonSymbol getSymbol(); - -} diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java index 14b7f5c..6704b92 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java @@ -23,7 +23,6 @@ public interface IonTypes { IElementType SEXPRESSION = new IonElementType("SEXPRESSION"); IElementType SEXPRESSION_ATOM = new IonElementType("SEXPRESSION_ATOM"); IElementType SEXPRESSION_ELEMENTS = new IonElementType("SEXPRESSION_ELEMENTS"); - IElementType SEXPRESSION_OPERATOR = new IonElementType("SEXPRESSION_OPERATOR"); IElementType STRING = new IonElementType("STRING"); IElementType STRUCT = new IonElementType("STRUCT"); IElementType SYMBOL = new IonElementType("SYMBOL"); @@ -114,9 +113,6 @@ else if (type == SEXPRESSION_ATOM) { else if (type == SEXPRESSION_ELEMENTS) { return new IonSexpressionElementsImpl(node); } - else if (type == SEXPRESSION_OPERATOR) { - return new IonSexpressionOperatorImpl(node); - } else if (type == STRING) { return new IonStringImpl(node); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java index cb9909a..9e0aedb 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java @@ -25,8 +25,7 @@ public interface IonValue extends PsiElement { @Nullable IonSymbol getSymbol(); - //WARNING: getValueAsString(...) is skipped - //matching getValueAsString(IonValue, ...) - //methods are not found in IonPsiUtil + @Nullable + String getValueAsString(); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java index 2836b5d..1281ab0 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java @@ -67,10 +67,6 @@ public void visitSexpressionElements(@NotNull IonSexpressionElements o) { visitPsiElement(o); } - public void visitSexpressionOperator(@NotNull IonSexpressionOperator o) { - visitPsiElement(o); - } - public void visitString(@NotNull IonString o) { visitPsiElement(o); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java index d6888b1..8a0a7fc 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java @@ -27,4 +27,10 @@ public void accept(@NotNull PsiElementVisitor visitor) { else super.accept(visitor); } + @Override + @Nullable + public String getKeyName() { + return IonPsiUtil.getKeyName(this); + } + } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java index b378a7b..7166da6 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java @@ -33,10 +33,4 @@ public List getSexpressionAtomList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, IonSexpressionAtom.class); } - @Override - @Nullable - public IonSexpressionOperator getSexpressionOperator() { - return findChildByClass(IonSexpressionOperator.class); - } - } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java deleted file mode 100644 index a85afac..0000000 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -// This is a generated file. Not intended for manual editing. -package com.amazon.ion.plugin.intellij.psi.impl; - -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.amazon.ion.plugin.intellij.psi.IonTypes.*; -import com.intellij.extapi.psi.ASTWrapperPsiElement; -import com.amazon.ion.plugin.intellij.psi.*; - -public class IonSexpressionOperatorImpl extends ASTWrapperPsiElement implements IonSexpressionOperator { - - public IonSexpressionOperatorImpl(@NotNull ASTNode node) { - super(node); - } - - public void accept(@NotNull IonVisitor visitor) { - visitor.visitSexpressionOperator(this); - } - - @Override - public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof IonVisitor) accept((IonVisitor)visitor); - else super.accept(visitor); - } - - @Override - @NotNull - public List getAnnotationList() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, IonAnnotation.class); - } - - @Override - @NotNull - public IonSymbol getSymbol() { - return findNotNullChildByClass(IonSymbol.class); - } - -} diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java index 25e6ff1..0cef5e6 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java @@ -63,4 +63,10 @@ public IonSymbol getSymbol() { return findChildByClass(IonSymbol.class); } + @Override + @Nullable + public String getValueAsString() { + return IonPsiUtil.getValueAsString(this); + } + } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf b/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf index 9f9a502..e14eede 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf @@ -24,8 +24,7 @@ key ::= (QUOTE KEY_NAME QUOTE) | (QQUOTE KEY_NAME QQUOTE) | (QQQUOTE KEY_NAME QQ list ::= LBRACKET [list_elements] RBRACKET {pin=1} list_elements ::= list_element* sexpression ::= (LPAREN [sexpression_elements] RPAREN) -sexpression_elements ::= [sexpression_operator] atoms* -sexpression_operator ::= (annotation)* (symbol) +sexpression_elements ::= atoms* sexpression_atom ::= OPERATOR | value {pin(".*")=1 recoverWhile=not_paren_or_next_member} blob ::= LOB_START (BLOB_VALUE | BAD_CHARACTER) LOB_END diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt index 67865f0..50768f8 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt @@ -33,9 +33,8 @@ class IonBreadcrumbsInfoProvider: BreadcrumbsProvider { is IonMembers -> (element as? IonPair)?.key?.text ?: "" is IonListElements -> p.valueList.indexOf(element).takeIf { it >= 0 }?.let { "[$it]" } ?: "" is IonSexpressionElements -> when (element) { - is IonSexpressionOperator -> "(0)" is IonSexpressionAtom -> { - val offset = if (p.sexpressionOperator != null) 1 else 0 + val offset = 0 p.sexpressionAtomList.indexOf(element) .takeIf { it >= 0 } ?.let { "(${it + offset})" } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt index 5b96cc6..88c385f 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt @@ -95,7 +95,6 @@ private fun createSpaceBuilder(settings: CodeStyleSettings) = * ) */ - before(IonTypes.SEXPRESSION_OPERATOR).none() before(IonTypes.RPAREN).lineBreakInCode() beforeInside(IonTypes.SEXPRESSION_ATOM, IonTypes.SEXPRESSION).lineBreakInCode() diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt index 07b1260..1364bb5 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt @@ -31,7 +31,6 @@ import com.amazon.ion.plugin.intellij.psi.IonTypes.RBRACE import com.amazon.ion.plugin.intellij.psi.IonTypes.RBRACKET import com.amazon.ion.plugin.intellij.psi.IonTypes.RPAREN import com.amazon.ion.plugin.intellij.psi.IonTypes.SEPARATOR -import com.amazon.ion.plugin.intellij.psi.IonTypes.SEXPRESSION_OPERATOR import com.amazon.ion.plugin.intellij.psi.IonTypes.TIMESTAMP import com.intellij.openapi.editor.DefaultLanguageHighlighterColors import com.intellij.openapi.editor.HighlighterColors @@ -78,7 +77,6 @@ object IonSyntaxHighlight { val Tokens = mapOf( tokenSet(SEPARATOR) to arrayOf(Attributes.Separator), tokenSet(KEY_NAME) to arrayOf(Attributes.StructKey), - tokenSet(SEXPRESSION_OPERATOR) to arrayOf(Attributes.IonSExpressionOperator), tokenSet(INTEGER, DECIMAL, HEXINT, BININT) to arrayOf(Attributes.IonNumber), tokenSet(BOOLEAN, NULL) to arrayOf(Attributes.IonBool), tokenSet(ANNOTATION) to arrayOf(Attributes.Annotation), diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt index 0ca86bf..ebbcc23 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt @@ -2,7 +2,6 @@ package com.amazon.ion.plugin.intellij.highlight.annotations import com.amazon.ion.plugin.intellij.highlight.IonSyntaxHighlight import com.amazon.ion.plugin.intellij.psi.IonTypes.ANNOTATION -import com.amazon.ion.plugin.intellij.psi.IonTypes.SEXPRESSION_OPERATOR /** * Annotates basic constructs within Ion. @@ -15,10 +14,6 @@ class BasicIonAnnotator : IonSyntaxAnnotator { element parentIsA ANNOTATION -> addSilentTextAttributes(IonSyntaxHighlight.Attributes.Annotation) - // Expression operators their parent of their parent is an expression operator - element.parent parentIsA SEXPRESSION_OPERATOR -> - addSilentTextAttributes(IonSyntaxHighlight.Attributes.IonSExpressionOperator) - else -> { /* do nothing */ } } } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt deleted file mode 100644 index 6bef82b..0000000 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.amazon.ion.plugin.intellij.markers - -import com.amazon.ion.plugin.intellij.IonIcons -import com.amazon.ion.plugin.intellij.psi.IonSexpressionOperator -import com.amazon.ion.plugin.intellij.utils.IonSearchUtils -import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo -import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider -import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.util.EmptyQuery -import com.intellij.util.Query - -/** - * Searches for Ion Operators in Kotlin Code and links to them from Ion code. - */ -class JavaIonOperatorMarkerProvider : RelatedItemLineMarkerProvider() { - override fun collectNavigationMarkers( - element: PsiElement, - result: MutableCollection> - ) { - element.javaIonOperators().forEach { - val builder = - NavigationGutterIconBuilder.create(IonIcons.Pluggable) - .setTarget(it) - .setTooltipText("Navigate to operator") - - result.add(builder.createLineMarkerInfo(element)) - } - } - - private fun PsiElement.javaIonOperators(): Query { - val ionOperatorExpression = this as? IonSexpressionOperator ?: return EmptyQuery() - val operatorName = ionOperatorExpression.text ?: return EmptyQuery() - return IonSearchUtils.queryJavaIonOperators(project) - .allowParallelProcessing() - .filtering { it.name?.startsWith(operatorName) != true } - } -} diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt index 15f9fd9..1da3fc7 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt @@ -44,7 +44,6 @@ class IonStructureViewElement(private val element: PsiElement) : StructureViewTr is IonStruct -> element.members?.pairList?.map { IonStructureViewElement(it) }?.toTypedArray() is IonSexpression -> listOfNotNull( - listOfNotNull(element.sexpressionElements?.sexpressionOperator?.let { IonStructureViewElement(it) }), element.sexpressionElements?.sexpressionAtomList?.getViewElementChildren() ).flatten().toTypedArray() diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt index 7e714eb..e6ba2cc 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt @@ -2,7 +2,6 @@ package com.amazon.ion.plugin.intellij.utils import com.amazon.ion.plugin.intellij.IonLanguageFileType import com.amazon.ion.plugin.intellij.psi.IonFile -import com.amazon.ion.plugin.intellij.psi.IonSexpressionOperator import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass @@ -26,17 +25,4 @@ object IonSearchUtils { val ionOperatorClazz = javaPsiFacade.findClass(ION_OPERATOR_JAVA_CLASS_NAME, scope) ?: return EmptyQuery() return ClassInheritorsSearch.search(ionOperatorClazz) } - - fun findIonExpressionOperators(project: Project): List { - val psiManager = PsiManager.getInstance(project) - val ionFiles = FileTypeIndex.getFiles(IonLanguageFileType.INSTANCE, GlobalSearchScope.allScope(project)) - - return ionFiles.flatMap { - val ionFile = psiManager.findFile(it) as? IonFile ?: return emptyList() - PsiTreeUtil.getChildrenOfType(ionFile, IonSexpressionOperator::class.java)?.toList() ?: emptyList() - } - } - - fun findIonExpressionOperators(project: Project, name: String): List = - findIonExpressionOperators(project).filter { !it.textMatches(name) } } diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt index ad835dd..0dc5733 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt @@ -69,8 +69,10 @@ class IonBasicFormattingTest : IonFormatterTestBase() { memberA: true, // Inner struct comment memberB: false, - transform: (join - (inner + transform: ( + join + ( + inner element ) { @@ -95,8 +97,10 @@ class IonBasicFormattingTest : IonFormatterTestBase() { ) """, """ - (expression // special case comment inline with expression does not move - (inner + ( + expression // special case comment inline with expression does not move + ( + inner expression ) { diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt index b2c21e4..2be3e77 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt @@ -135,27 +135,4 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { PsiElement(RPAREN)(')') """ ) - - fun `test sexp with SEXPRESSION operator`() = doTest( - """ - (test element) - """, - """ - Ion File - IonValueImpl(VALUE) - IonContainerImpl(CONTAINER) - IonSexpressionImpl(SEXPRESSION) - PsiElement(LPAREN)('(') - IonSexpressionElementsImpl(SEXPRESSION_ELEMENTS) - IonSexpressionOperatorImpl(SEXPRESSION_OPERATOR) - IonSymbolImpl(SYMBOL) - PsiElement(IDENTIFIER)('test') - PsiWhiteSpace(' ') - IonSexpressionAtomImpl(SEXPRESSION_ATOM) - IonValueImpl(VALUE) - IonSymbolImpl(SYMBOL) - PsiElement(IDENTIFIER)('element') - PsiElement(RPAREN)(')') - """ - ) } From 5c0f9b91ec007c226c0a6c9332e6f2984de261b3 Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Mon, 10 Jun 2024 14:00:39 -0700 Subject: [PATCH 5/5] Revert "Removes treating first element as operator in SExp" This reverts commit c489a4ed70fb6807c4ad3407efc1240caf2cb23e. --- .../formatting/blocks/IonSExpressionBlock.kt | 33 ++++++++++ .../formatting/blocks/IonSExpressionBlock.kt | 33 ++++++++++ .../formatting/blocks/IonSExpressionBlock.kt | 33 ++++++++++ .../formatting/blocks/IonSExpressionBlock.kt | 33 ++++++++++ .../formatting/blocks/IonSExpressionBlock.kt | 33 ++++++++++ .../amazon/ion/plugin/intellij/IonParser.java | 66 ++++++++++++++++++- .../ion/plugin/intellij/psi/IonKey.java | 5 +- .../intellij/psi/IonSexpressionElements.java | 3 + .../intellij/psi/IonSexpressionOperator.java | 16 +++++ .../ion/plugin/intellij/psi/IonTypes.java | 4 ++ .../ion/plugin/intellij/psi/IonValue.java | 5 +- .../ion/plugin/intellij/psi/IonVisitor.java | 4 ++ .../plugin/intellij/psi/impl/IonKeyImpl.java | 6 -- .../psi/impl/IonSexpressionElementsImpl.java | 6 ++ .../psi/impl/IonSexpressionOperatorImpl.java | 42 ++++++++++++ .../intellij/psi/impl/IonValueImpl.java | 6 -- .../com/amazon/ion/plugin/intellij/Ion.bnf | 3 +- .../breadcrumb/IonBreadcrumbsInfoProvider.kt | 3 +- .../formatting/IonCodeBlockSpacingProvider.kt | 1 + .../intellij/highlight/IonSyntaxHighlight.kt | 2 + .../annotations/BasicIonAnnotator.kt | 5 ++ .../markers/JavaIonOperatorMarkerProvider.kt | 39 +++++++++++ .../structure/IonStructureViewElement.kt | 1 + .../plugin/intellij/utils/IonSearchUtils.kt | 14 ++++ .../formatting/IonBasicFormattingTest.kt | 12 ++-- .../intellij/parser/IonBasicParsingTest.kt | 23 +++++++ 26 files changed, 402 insertions(+), 29 deletions(-) create mode 100644 src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java create mode 100644 src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java create mode 100644 src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt diff --git a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 596ce89..7aeff8d 100644 --- a/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-222/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,4 +32,37 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) + + override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = + buildSpecialCaseChildBlockFormatting(child) ?: + super.buildChildBlockFormatting(child) + + private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { + + // Lazy evaluate the previous sibling if needed. + val previous by lazy { child.previousSibling() } + + /** + * Check if we are the first comment within the expression, there is a special comment + * case where we don't want to apply the child alignment to the comment. For example: + * + * (join // special case comment which is inline with operator + * // child comments are inline with inner values + * anotherValue + * ) + */ + if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { + + logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } + + val comment = child.psi + val expressionOperator = previous!! + + if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { + return IonBlockFormatting.sameAlignment(this) + } + } + + return null + } } diff --git a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 1b138e1..ac0223e 100644 --- a/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-231/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,4 +32,37 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) + + override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = + buildSpecialCaseChildBlockFormatting(child) ?: + super.buildChildBlockFormatting(child) + + private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { + + // Lazy evaluate the previous sibling if needed. + val previous by lazy { child.previousSibling() } + + /** + * Check if we are the first comment within the expression, there is a special comment + * case where we don't want to apply the child alignment to the comment. For example: + * + * (join // special case comment which is inline with operator + * // child comments are inline with inner values + * anotherValue + * ) + */ + if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { + + logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } + + val comment = child.psi + val expressionOperator = previous!! + + if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { + return IonBlockFormatting.sameAlignment(this) + } + } + + return null + } } diff --git a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 1b138e1..ac0223e 100644 --- a/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-232/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,4 +32,37 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) + + override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = + buildSpecialCaseChildBlockFormatting(child) ?: + super.buildChildBlockFormatting(child) + + private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { + + // Lazy evaluate the previous sibling if needed. + val previous by lazy { child.previousSibling() } + + /** + * Check if we are the first comment within the expression, there is a special comment + * case where we don't want to apply the child alignment to the comment. For example: + * + * (join // special case comment which is inline with operator + * // child comments are inline with inner values + * anotherValue + * ) + */ + if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { + + logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } + + val comment = child.psi + val expressionOperator = previous!! + + if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { + return IonBlockFormatting.sameAlignment(this) + } + } + + return null + } } diff --git a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 1b138e1..ac0223e 100644 --- a/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-233/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,4 +32,37 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) + + override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = + buildSpecialCaseChildBlockFormatting(child) ?: + super.buildChildBlockFormatting(child) + + private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { + + // Lazy evaluate the previous sibling if needed. + val previous by lazy { child.previousSibling() } + + /** + * Check if we are the first comment within the expression, there is a special comment + * case where we don't want to apply the child alignment to the comment. For example: + * + * (join // special case comment which is inline with operator + * // child comments are inline with inner values + * anotherValue + * ) + */ + if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { + + logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } + + val comment = child.psi + val expressionOperator = previous!! + + if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { + return IonBlockFormatting.sameAlignment(this) + } + } + + return null + } } diff --git a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt index 1b138e1..ac0223e 100644 --- a/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt +++ b/src/IC-241/kotlin/com/amazon/ion/plugin/intellij/formatting/blocks/IonSExpressionBlock.kt @@ -32,4 +32,37 @@ class IonSExpressionBlock( IonTypes.LPAREN, IonTypes.RPAREN ) + + override fun buildChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions = + buildSpecialCaseChildBlockFormatting(child) ?: + super.buildChildBlockFormatting(child) + + private fun buildSpecialCaseChildBlockFormatting(child: ASTNode): IonBlockFormattingOptions? { + + // Lazy evaluate the previous sibling if needed. + val previous by lazy { child.previousSibling() } + + /** + * Check if we are the first comment within the expression, there is a special comment + * case where we don't want to apply the child alignment to the comment. For example: + * + * (join // special case comment which is inline with operator + * // child comments are inline with inner values + * anotherValue + * ) + */ + if (child elementIsA IonTypes.COMMENT && previous?.elementType == IonTypes.SEXPRESSION_OPERATOR) { + + logger.debug { "Formatting [${child.psi.getLineNumber()}] - Special case inline expression comment line" } + + val comment = child.psi + val expressionOperator = previous!! + + if (comment.isOneLiner() && child.sameLineAs(expressionOperator)) { + return IonBlockFormatting.sameAlignment(this) + } + } + + return null + } } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java b/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java index 27486a6..0d48577 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/IonParser.java @@ -472,19 +472,79 @@ public static boolean sexpression_atom(PsiBuilder b, int l) { } /* ********************************************************** */ - // atoms* + // [sexpression_operator] atoms* public static boolean sexpression_elements(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "sexpression_elements")) return false; + boolean r; Marker m = enter_section_(b, l, _NONE_, SEXPRESSION_ELEMENTS, ""); + r = sexpression_elements_0(b, l + 1); + r = r && sexpression_elements_1(b, l + 1); + exit_section_(b, l, m, r, false, null); + return r; + } + + // [sexpression_operator] + private static boolean sexpression_elements_0(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_elements_0")) return false; + sexpression_operator(b, l + 1); + return true; + } + + // atoms* + private static boolean sexpression_elements_1(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_elements_1")) return false; while (true) { int c = current_position_(b); if (!atoms(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "sexpression_elements", c)) break; + if (!empty_element_parsed_guard_(b, "sexpression_elements_1", c)) break; } - exit_section_(b, l, m, true, false, null); return true; } + /* ********************************************************** */ + // (annotation)* (symbol) + public static boolean sexpression_operator(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_operator")) return false; + if (!nextTokenIs(b, "", IDENTIFIER, Q_START)) return false; + boolean r; + Marker m = enter_section_(b, l, _NONE_, SEXPRESSION_OPERATOR, ""); + r = sexpression_operator_0(b, l + 1); + r = r && sexpression_operator_1(b, l + 1); + exit_section_(b, l, m, r, false, null); + return r; + } + + // (annotation)* + private static boolean sexpression_operator_0(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_operator_0")) return false; + while (true) { + int c = current_position_(b); + if (!sexpression_operator_0_0(b, l + 1)) break; + if (!empty_element_parsed_guard_(b, "sexpression_operator_0", c)) break; + } + return true; + } + + // (annotation) + private static boolean sexpression_operator_0_0(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_operator_0_0")) return false; + boolean r; + Marker m = enter_section_(b); + r = annotation(b, l + 1); + exit_section_(b, m, null, r); + return r; + } + + // (symbol) + private static boolean sexpression_operator_1(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "sexpression_operator_1")) return false; + boolean r; + Marker m = enter_section_(b); + r = symbol(b, l + 1); + exit_section_(b, m, null, r); + return r; + } + /* ********************************************************** */ // qqq_string | qq_string public static boolean string(PsiBuilder b, int l) { diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java index af18df1..0bfca54 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonKey.java @@ -7,7 +7,8 @@ public interface IonKey extends PsiElement { - @Nullable - String getKeyName(); + //WARNING: getKeyName(...) is skipped + //matching getKeyName(IonKey, ...) + //methods are not found in IonPsiUtil } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java index 1218fc1..6d5e700 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionElements.java @@ -10,4 +10,7 @@ public interface IonSexpressionElements extends PsiElement { @NotNull List getSexpressionAtomList(); + @Nullable + IonSexpressionOperator getSexpressionOperator(); + } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java new file mode 100644 index 0000000..1845304 --- /dev/null +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonSexpressionOperator.java @@ -0,0 +1,16 @@ +// This is a generated file. Not intended for manual editing. +package com.amazon.ion.plugin.intellij.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface IonSexpressionOperator extends PsiElement { + + @NotNull + List getAnnotationList(); + + @NotNull + IonSymbol getSymbol(); + +} diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java index 6704b92..14b7f5c 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonTypes.java @@ -23,6 +23,7 @@ public interface IonTypes { IElementType SEXPRESSION = new IonElementType("SEXPRESSION"); IElementType SEXPRESSION_ATOM = new IonElementType("SEXPRESSION_ATOM"); IElementType SEXPRESSION_ELEMENTS = new IonElementType("SEXPRESSION_ELEMENTS"); + IElementType SEXPRESSION_OPERATOR = new IonElementType("SEXPRESSION_OPERATOR"); IElementType STRING = new IonElementType("STRING"); IElementType STRUCT = new IonElementType("STRUCT"); IElementType SYMBOL = new IonElementType("SYMBOL"); @@ -113,6 +114,9 @@ else if (type == SEXPRESSION_ATOM) { else if (type == SEXPRESSION_ELEMENTS) { return new IonSexpressionElementsImpl(node); } + else if (type == SEXPRESSION_OPERATOR) { + return new IonSexpressionOperatorImpl(node); + } else if (type == STRING) { return new IonStringImpl(node); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java index 9e0aedb..cb9909a 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonValue.java @@ -25,7 +25,8 @@ public interface IonValue extends PsiElement { @Nullable IonSymbol getSymbol(); - @Nullable - String getValueAsString(); + //WARNING: getValueAsString(...) is skipped + //matching getValueAsString(IonValue, ...) + //methods are not found in IonPsiUtil } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java index 1281ab0..2836b5d 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/IonVisitor.java @@ -67,6 +67,10 @@ public void visitSexpressionElements(@NotNull IonSexpressionElements o) { visitPsiElement(o); } + public void visitSexpressionOperator(@NotNull IonSexpressionOperator o) { + visitPsiElement(o); + } + public void visitString(@NotNull IonString o) { visitPsiElement(o); } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java index 8a0a7fc..d6888b1 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonKeyImpl.java @@ -27,10 +27,4 @@ public void accept(@NotNull PsiElementVisitor visitor) { else super.accept(visitor); } - @Override - @Nullable - public String getKeyName() { - return IonPsiUtil.getKeyName(this); - } - } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java index 7166da6..b378a7b 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionElementsImpl.java @@ -33,4 +33,10 @@ public List getSexpressionAtomList() { return PsiTreeUtil.getChildrenOfTypeAsList(this, IonSexpressionAtom.class); } + @Override + @Nullable + public IonSexpressionOperator getSexpressionOperator() { + return findChildByClass(IonSexpressionOperator.class); + } + } diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java new file mode 100644 index 0000000..a85afac --- /dev/null +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonSexpressionOperatorImpl.java @@ -0,0 +1,42 @@ +// This is a generated file. Not intended for manual editing. +package com.amazon.ion.plugin.intellij.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.amazon.ion.plugin.intellij.psi.IonTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.amazon.ion.plugin.intellij.psi.*; + +public class IonSexpressionOperatorImpl extends ASTWrapperPsiElement implements IonSexpressionOperator { + + public IonSexpressionOperatorImpl(@NotNull ASTNode node) { + super(node); + } + + public void accept(@NotNull IonVisitor visitor) { + visitor.visitSexpressionOperator(this); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof IonVisitor) accept((IonVisitor)visitor); + else super.accept(visitor); + } + + @Override + @NotNull + public List getAnnotationList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, IonAnnotation.class); + } + + @Override + @NotNull + public IonSymbol getSymbol() { + return findNotNullChildByClass(IonSymbol.class); + } + +} diff --git a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java index 0cef5e6..25e6ff1 100644 --- a/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java +++ b/src/main/gen/com/amazon/ion/plugin/intellij/psi/impl/IonValueImpl.java @@ -63,10 +63,4 @@ public IonSymbol getSymbol() { return findChildByClass(IonSymbol.class); } - @Override - @Nullable - public String getValueAsString() { - return IonPsiUtil.getValueAsString(this); - } - } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf b/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf index e14eede..9f9a502 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/Ion.bnf @@ -24,7 +24,8 @@ key ::= (QUOTE KEY_NAME QUOTE) | (QQUOTE KEY_NAME QQUOTE) | (QQQUOTE KEY_NAME QQ list ::= LBRACKET [list_elements] RBRACKET {pin=1} list_elements ::= list_element* sexpression ::= (LPAREN [sexpression_elements] RPAREN) -sexpression_elements ::= atoms* +sexpression_elements ::= [sexpression_operator] atoms* +sexpression_operator ::= (annotation)* (symbol) sexpression_atom ::= OPERATOR | value {pin(".*")=1 recoverWhile=not_paren_or_next_member} blob ::= LOB_START (BLOB_VALUE | BAD_CHARACTER) LOB_END diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt index 50768f8..67865f0 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/breadcrumb/IonBreadcrumbsInfoProvider.kt @@ -33,8 +33,9 @@ class IonBreadcrumbsInfoProvider: BreadcrumbsProvider { is IonMembers -> (element as? IonPair)?.key?.text ?: "" is IonListElements -> p.valueList.indexOf(element).takeIf { it >= 0 }?.let { "[$it]" } ?: "" is IonSexpressionElements -> when (element) { + is IonSexpressionOperator -> "(0)" is IonSexpressionAtom -> { - val offset = 0 + val offset = if (p.sexpressionOperator != null) 1 else 0 p.sexpressionAtomList.indexOf(element) .takeIf { it >= 0 } ?.let { "(${it + offset})" } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt index 88c385f..5b96cc6 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/formatting/IonCodeBlockSpacingProvider.kt @@ -95,6 +95,7 @@ private fun createSpaceBuilder(settings: CodeStyleSettings) = * ) */ + before(IonTypes.SEXPRESSION_OPERATOR).none() before(IonTypes.RPAREN).lineBreakInCode() beforeInside(IonTypes.SEXPRESSION_ATOM, IonTypes.SEXPRESSION).lineBreakInCode() diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt index 1364bb5..07b1260 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/IonSyntaxHighlight.kt @@ -31,6 +31,7 @@ import com.amazon.ion.plugin.intellij.psi.IonTypes.RBRACE import com.amazon.ion.plugin.intellij.psi.IonTypes.RBRACKET import com.amazon.ion.plugin.intellij.psi.IonTypes.RPAREN import com.amazon.ion.plugin.intellij.psi.IonTypes.SEPARATOR +import com.amazon.ion.plugin.intellij.psi.IonTypes.SEXPRESSION_OPERATOR import com.amazon.ion.plugin.intellij.psi.IonTypes.TIMESTAMP import com.intellij.openapi.editor.DefaultLanguageHighlighterColors import com.intellij.openapi.editor.HighlighterColors @@ -77,6 +78,7 @@ object IonSyntaxHighlight { val Tokens = mapOf( tokenSet(SEPARATOR) to arrayOf(Attributes.Separator), tokenSet(KEY_NAME) to arrayOf(Attributes.StructKey), + tokenSet(SEXPRESSION_OPERATOR) to arrayOf(Attributes.IonSExpressionOperator), tokenSet(INTEGER, DECIMAL, HEXINT, BININT) to arrayOf(Attributes.IonNumber), tokenSet(BOOLEAN, NULL) to arrayOf(Attributes.IonBool), tokenSet(ANNOTATION) to arrayOf(Attributes.Annotation), diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt index ebbcc23..0ca86bf 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/highlight/annotations/BasicIonAnnotator.kt @@ -2,6 +2,7 @@ package com.amazon.ion.plugin.intellij.highlight.annotations import com.amazon.ion.plugin.intellij.highlight.IonSyntaxHighlight import com.amazon.ion.plugin.intellij.psi.IonTypes.ANNOTATION +import com.amazon.ion.plugin.intellij.psi.IonTypes.SEXPRESSION_OPERATOR /** * Annotates basic constructs within Ion. @@ -14,6 +15,10 @@ class BasicIonAnnotator : IonSyntaxAnnotator { element parentIsA ANNOTATION -> addSilentTextAttributes(IonSyntaxHighlight.Attributes.Annotation) + // Expression operators their parent of their parent is an expression operator + element.parent parentIsA SEXPRESSION_OPERATOR -> + addSilentTextAttributes(IonSyntaxHighlight.Attributes.IonSExpressionOperator) + else -> { /* do nothing */ } } } diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt new file mode 100644 index 0000000..6bef82b --- /dev/null +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/markers/JavaIonOperatorMarkerProvider.kt @@ -0,0 +1,39 @@ +package com.amazon.ion.plugin.intellij.markers + +import com.amazon.ion.plugin.intellij.IonIcons +import com.amazon.ion.plugin.intellij.psi.IonSexpressionOperator +import com.amazon.ion.plugin.intellij.utils.IonSearchUtils +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider +import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.util.EmptyQuery +import com.intellij.util.Query + +/** + * Searches for Ion Operators in Kotlin Code and links to them from Ion code. + */ +class JavaIonOperatorMarkerProvider : RelatedItemLineMarkerProvider() { + override fun collectNavigationMarkers( + element: PsiElement, + result: MutableCollection> + ) { + element.javaIonOperators().forEach { + val builder = + NavigationGutterIconBuilder.create(IonIcons.Pluggable) + .setTarget(it) + .setTooltipText("Navigate to operator") + + result.add(builder.createLineMarkerInfo(element)) + } + } + + private fun PsiElement.javaIonOperators(): Query { + val ionOperatorExpression = this as? IonSexpressionOperator ?: return EmptyQuery() + val operatorName = ionOperatorExpression.text ?: return EmptyQuery() + return IonSearchUtils.queryJavaIonOperators(project) + .allowParallelProcessing() + .filtering { it.name?.startsWith(operatorName) != true } + } +} diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt index 1da3fc7..15f9fd9 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/structure/IonStructureViewElement.kt @@ -44,6 +44,7 @@ class IonStructureViewElement(private val element: PsiElement) : StructureViewTr is IonStruct -> element.members?.pairList?.map { IonStructureViewElement(it) }?.toTypedArray() is IonSexpression -> listOfNotNull( + listOfNotNull(element.sexpressionElements?.sexpressionOperator?.let { IonStructureViewElement(it) }), element.sexpressionElements?.sexpressionAtomList?.getViewElementChildren() ).flatten().toTypedArray() diff --git a/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt b/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt index e6ba2cc..7e714eb 100644 --- a/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt +++ b/src/main/kotlin/com/amazon/ion/plugin/intellij/utils/IonSearchUtils.kt @@ -2,6 +2,7 @@ package com.amazon.ion.plugin.intellij.utils import com.amazon.ion.plugin.intellij.IonLanguageFileType import com.amazon.ion.plugin.intellij.psi.IonFile +import com.amazon.ion.plugin.intellij.psi.IonSexpressionOperator import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass @@ -25,4 +26,17 @@ object IonSearchUtils { val ionOperatorClazz = javaPsiFacade.findClass(ION_OPERATOR_JAVA_CLASS_NAME, scope) ?: return EmptyQuery() return ClassInheritorsSearch.search(ionOperatorClazz) } + + fun findIonExpressionOperators(project: Project): List { + val psiManager = PsiManager.getInstance(project) + val ionFiles = FileTypeIndex.getFiles(IonLanguageFileType.INSTANCE, GlobalSearchScope.allScope(project)) + + return ionFiles.flatMap { + val ionFile = psiManager.findFile(it) as? IonFile ?: return emptyList() + PsiTreeUtil.getChildrenOfType(ionFile, IonSexpressionOperator::class.java)?.toList() ?: emptyList() + } + } + + fun findIonExpressionOperators(project: Project, name: String): List = + findIonExpressionOperators(project).filter { !it.textMatches(name) } } diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt index 0dc5733..ad835dd 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/formatting/IonBasicFormattingTest.kt @@ -69,10 +69,8 @@ class IonBasicFormattingTest : IonFormatterTestBase() { memberA: true, // Inner struct comment memberB: false, - transform: ( - join - ( - inner + transform: (join + (inner element ) { @@ -97,10 +95,8 @@ class IonBasicFormattingTest : IonFormatterTestBase() { ) """, """ - ( - expression // special case comment inline with expression does not move - ( - inner + (expression // special case comment inline with expression does not move + (inner expression ) { diff --git a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt index 2be3e77..b2c21e4 100644 --- a/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt +++ b/src/test/kotlin/com/amazon/ion/plugin/intellij/parser/IonBasicParsingTest.kt @@ -135,4 +135,27 @@ class IonBasicParsingTest : IonParserTestCaseBase(dataPath = "basic") { PsiElement(RPAREN)(')') """ ) + + fun `test sexp with SEXPRESSION operator`() = doTest( + """ + (test element) + """, + """ + Ion File + IonValueImpl(VALUE) + IonContainerImpl(CONTAINER) + IonSexpressionImpl(SEXPRESSION) + PsiElement(LPAREN)('(') + IonSexpressionElementsImpl(SEXPRESSION_ELEMENTS) + IonSexpressionOperatorImpl(SEXPRESSION_OPERATOR) + IonSymbolImpl(SYMBOL) + PsiElement(IDENTIFIER)('test') + PsiWhiteSpace(' ') + IonSexpressionAtomImpl(SEXPRESSION_ATOM) + IonValueImpl(VALUE) + IonSymbolImpl(SYMBOL) + PsiElement(IDENTIFIER)('element') + PsiElement(RPAREN)(')') + """ + ) }