Skip to content

Commit d434d9e

Browse files
committed
(#182) Parser: update the approach to newline recognition
For #182, we want to distinguish a single newline versus several newlines in a PowerShell file. This change allows that.
1 parent 3d67053 commit d434d9e

File tree

7 files changed

+27
-30
lines changed

7 files changed

+27
-30
lines changed

src/main/kotlin/com/intellij/plugin/powershell/ide/editor/PowerShellFoldingBuilder.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class PowerShellFoldingBuilder : CustomFoldingBuilder(), DumbAware {
8686

8787
fun PsiElement.getNextSiblingNonWhiteSpace(): PsiElement? {
8888
var next = this.nextSibling
89-
while (next != null && (next is PsiWhiteSpace || next.node.elementType == NLS)) {
89+
while (next != null && (next is PsiWhiteSpace || next.node.elementType == NEWLINE)) {
9090
next = next.nextSibling
9191
}
9292
return next

src/main/kotlin/com/intellij/plugin/powershell/ide/editor/formatting/PSFormattingUtils.kt

+6-6
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ internal fun isSwitchStatementContext(node: ASTNode): Boolean {
5050

5151
//internal fun isFirstInChainedCall(node: ASTNode): Boolean {
5252
// if (node.treeParent?.elementType !== PowerShellTypes.INVOCATION_EXPRESSION) return false
53-
// return findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE, PowerShellTypes.DOT, PowerShellTypes.COLON2), false)?.elementType !== PowerShellTypes.INVOCATION_EXPRESSION
53+
// return findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE, PowerShellTypes.DOT, PowerShellTypes.COLON2), false)?.elementType !== PowerShellTypes.INVOCATION_EXPRESSION
5454
//}
5555

5656
internal fun isSubExpressionContext(node: ASTNode): Boolean {
@@ -231,16 +231,16 @@ internal fun isParenthesizedExpressionContext(node: ASTNode): Boolean {
231231
return node.treeParent?.elementType === PowerShellTypes.PARENTHESIZED_EXPRESSION
232232
}
233233

234-
internal fun isFollowedByAttribute(childNode: ASTNode) = findSiblingSkipping(childNode, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), false)?.elementType === PowerShellTypes.ATTRIBUTE
234+
internal fun isFollowedByAttribute(childNode: ASTNode) = findSiblingSkipping(childNode, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), false)?.elementType === PowerShellTypes.ATTRIBUTE
235235

236236
internal fun isRhsBinaryExpressionContext(node: ASTNode): Boolean {
237237
if (!isBinaryExpressionContext(node)) return false
238-
val type = findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), false)?.elementType
238+
val type = findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), false)?.elementType
239239
return node.psi is PowerShellExpression && PowerShellTokenTypeSets.OPERATORS.contains(type)
240240
}
241241

242242
internal fun isFirstNodeInForParameter(node: ASTNode): Boolean {
243-
val prevIEType = findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), false)?.elementType
243+
val prevIEType = findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), false)?.elementType
244244
return node.treeParent.elementType === PowerShellTypes.FOR_CLAUSE && (prevIEType === PowerShellTypes.SEMI || prevIEType === PowerShellTypes.LP)
245245
}
246246

@@ -258,12 +258,12 @@ internal fun isArrayElement(node: ASTNode): Boolean {
258258

259259
internal fun isInvocationExpressionQualifier(node: ASTNode): Boolean {
260260
if (node.treeParent?.elementType !== PowerShellTypes.INVOCATION_EXPRESSION) return false
261-
val prevElement = findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), false)?.elementType
261+
val prevElement = findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), false)?.elementType
262262
return (prevElement === PowerShellTypes.DOT || prevElement === PowerShellTypes.COLON2) && (node.elementType === PowerShellTypes.REFERENCE_IDENTIFIER || node.psi is PowerShellExpression)
263263
}
264264

265265
internal fun isFirstNodeInParameter(node: ASTNode, checkFirstParameter: Boolean = false): Boolean {
266-
val prevSibling = findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), false)
266+
val prevSibling = findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), false)
267267
return prevSibling != null && (prevSibling.elementType === PowerShellTypes.COMMA || (checkFirstParameter && prevSibling.elementType === PowerShellTypes.LP))
268268
}
269269

src/main/kotlin/com/intellij/plugin/powershell/ide/editor/formatting/PowerShellBlockImpl.kt

+9-9
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ open class PowerShellBlockImpl(node: ASTNode, wrap: Wrap?, alignment: Alignment?
132132
val type = child.elementType
133133
if (type === INVOCATION_EXPRESSION) {
134134
collectNodes(nodes, child)
135-
} else if (type !== NLS) {
135+
} else if (type !== NEWLINE) {
136136
nodes.add(child)
137137
}
138138
}
@@ -225,7 +225,7 @@ open class PowerShellBlockImpl(node: ASTNode, wrap: Wrap?, alignment: Alignment?
225225
}
226226

227227
private fun createWrap(childNode: ASTNode): Wrap {
228-
if ((isFunctionParameter(childNode) || isBlockParameter(childNode)) && findSiblingSkipping(childNode, arrayOf(NLS, WHITE_SPACE), false)?.elementType != LP) {
228+
if ((isFunctionParameter(childNode) || isBlockParameter(childNode)) && findSiblingSkipping(childNode, arrayOf(NEWLINE, WHITE_SPACE), false)?.elementType != LP) {
229229
val firstNode = isFirstNodeInParameter(childNode, true)
230230
val wrapValue = if (isFunctionParameter(childNode)) myCommonSettings.METHOD_PARAMETERS_WRAP else myPSSettings.BLOCK_PARAMETER_CLAUSE_WRAP
231231
val paramWrap = Wrap.createWrap(WrappingUtil.getWrapType(wrapValue), firstNode)
@@ -246,7 +246,7 @@ open class PowerShellBlockImpl(node: ASTNode, wrap: Wrap?, alignment: Alignment?
246246
return paramWrap
247247
}
248248

249-
if (isCallArgument(childNode) && findSiblingSkipping(childNode, arrayOf(NLS, WHITE_SPACE), false)?.elementType != LP) {
249+
if (isCallArgument(childNode) && findSiblingSkipping(childNode, arrayOf(NEWLINE, WHITE_SPACE), false)?.elementType != LP) {
250250
return Wrap.createWrap(WrappingUtil.getWrapType(myCommonSettings.CALL_PARAMETERS_WRAP), isFirstNodeInParameter(childNode, true))
251251
}
252252

@@ -373,7 +373,7 @@ class PowerShellSpacingProcessor(private val myCommonSettings: CommonCodeStyleSe
373373

374374
if (LCURLY === type1 || RCURLY === type2) {
375375
val braceNode = if (LCURLY === type1) node1 else node2
376-
val blockBody = findSiblingSkipping(braceNode, arrayOf(NLS, WHITE_SPACE), braceNode === node1)
376+
val blockBody = findSiblingSkipping(braceNode, arrayOf(NEWLINE, WHITE_SPACE), braceNode === node1)
377377
val blockBodyToken = blockBody?.elementType
378378
if (blockBodyToken === IDENTIFIER || blockBodyToken === SIMPLE_ID) return null
379379

@@ -403,7 +403,7 @@ class PowerShellSpacingProcessor(private val myCommonSettings: CommonCodeStyleSe
403403

404404
if (LP === type1) {
405405
if (isArgumentListContext(node1)) {
406-
val treeNext = findSiblingSkipping(node1, arrayOf(NLS, WHITE_SPACE))
406+
val treeNext = findSiblingSkipping(node1, arrayOf(NEWLINE, WHITE_SPACE))
407407
val lfAfterLparen = myCommonSettings.CALL_PARAMETERS_WRAP != DO_NOT_WRAP && myCommonSettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE
408408
if (treeNext?.elementType === RP) {
409409
val lfAfterRparen = myCommonSettings.CALL_PARAMETERS_WRAP != DO_NOT_WRAP && myCommonSettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE
@@ -413,7 +413,7 @@ class PowerShellSpacingProcessor(private val myCommonSettings: CommonCodeStyleSe
413413
return createSpacing(myCommonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, lfAfterLparen)
414414
}
415415
if (isParameterClauseContext(node1) || isBlockParameterClauseContext(node1)) {
416-
val treeNext = findSiblingSkipping(node1, arrayOf(NLS, WHITE_SPACE))
416+
val treeNext = findSiblingSkipping(node1, arrayOf(NEWLINE, WHITE_SPACE))
417417
val methodParam = isParameterClauseContext(node1)
418418
val wrapValue = if (methodParam) myCommonSettings.METHOD_PARAMETERS_WRAP else myPowerShellSettings.BLOCK_PARAMETER_CLAUSE_WRAP
419419
val lParenNextLine = if (methodParam) myCommonSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE else myPowerShellSettings.BLOCK_PARAMETERS_LPAREN_ON_NEXT_LINE
@@ -447,14 +447,14 @@ class PowerShellSpacingProcessor(private val myCommonSettings: CommonCodeStyleSe
447447
}
448448
if (RP === type2) {
449449
if (isArgumentListContext(node2)) {
450-
val treePrev = findSiblingSkipping(node2, arrayOf(NLS, WHITE_SPACE), false)
450+
val treePrev = findSiblingSkipping(node2, arrayOf(NEWLINE, WHITE_SPACE), false)
451451
val lfAfterRparen = myCommonSettings.CALL_PARAMETERS_WRAP != DO_NOT_WRAP && myCommonSettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE
452452
if (treePrev?.elementType === LP) return createSpacing(myCommonSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES, lfAfterRparen)
453453

454454
return createSpacing(myCommonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, lfAfterRparen)
455455
}
456456
if (isParameterClauseContext(node2) || isBlockParameterClauseContext(node1)) {
457-
val treePrev = findSiblingSkipping(node2, arrayOf(NLS, WHITE_SPACE), false)
457+
val treePrev = findSiblingSkipping(node2, arrayOf(NEWLINE, WHITE_SPACE), false)
458458
val methodParam = isParameterClauseContext(node2)
459459
val wrapValue = if (methodParam) myCommonSettings.METHOD_PARAMETERS_WRAP else myPowerShellSettings.BLOCK_PARAMETER_CLAUSE_WRAP
460460
val rParenNextLine = if (methodParam) myCommonSettings.METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE else myPowerShellSettings.BLOCK_PARAMETERS_RPAREN_ON_NEXT_LINE
@@ -641,7 +641,7 @@ class PowerShellSpacingProcessor(private val myCommonSettings: CommonCodeStyleSe
641641

642642
if (type2 == SEMI) return simpleSpacing(myCommonSettings.SPACE_BEFORE_SEMICOLON)
643643

644-
if ((PowerShellTokenTypeSets.KEYWORDS.contains(type1) && !isIdentifier(node1.treeParent)/*|| HANDLER_PARAMETER_LABEL === type1*/) && NLS !== type2) {
644+
if ((PowerShellTokenTypeSets.KEYWORDS.contains(type1) && !isIdentifier(node1.treeParent)/*|| HANDLER_PARAMETER_LABEL === type1*/) && NEWLINE !== type2) {
645645
return Spacing.createSpacing(1, 1, 0, true, 0)
646646
}
647647

src/main/kotlin/com/intellij/plugin/powershell/psi/PowerShellPsiUtil.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal fun findSiblingSkipping(node: ASTNode, toSkip: Array<IElementType>, for
1616
}
1717

1818
internal fun findSiblingSkippingWS(node: ASTNode, forward: Boolean = true): ASTNode? {
19-
return findSiblingSkipping(node, arrayOf(PowerShellTypes.NLS, TokenType.WHITE_SPACE), forward)
19+
return findSiblingSkipping(node, arrayOf(PowerShellTypes.NEWLINE, TokenType.WHITE_SPACE), forward)
2020
}
2121

2222
fun isTargetVariableContext(node: ASTNode): Boolean {
@@ -29,4 +29,4 @@ fun isFunctionDeclarationContext(node: ASTNode): Boolean {
2929

3030
fun isPathExpressionContext(node: ASTNode): Boolean {
3131
return node.treeParent.elementType == PATH_EXPRESSION
32-
}
32+
}

src/main/kotlin/com/intellij/plugin/powershell/psi/impl/PowerShellPsiImplUtil.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ private fun isWhiteSpace(node: ASTNode): Boolean {
1414
}
1515

1616
fun ASTNode.isWhiteSpaceOrNls(): Boolean {
17-
return isWhiteSpace(this) || elementType === PowerShellTypes.NLS || elementType === PowerShellTypes.LF
17+
return isWhiteSpace(this) || elementType === PowerShellTypes.NEWLINE || elementType === PowerShellTypes.LF
1818
}
1919

2020
val PowerShellAssignmentExpression.targetVariables: List<PowerShellTargetVariableExpression>

src/main/resources/PowerShell.bnf

+5-7
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@
2626
OP_BNOT='-bnot'
2727
EXCL_MARK='!'
2828

29-
// NewLines and spaces //
30-
NLS ='regexp:[\ \t\f]*(\r|\n|\r\n)((\r|\n|\r\n)|([\ \t\f])*)*'
31-
LF = 'regexp:(\r|\n|\r\n)+'
32-
29+
// A single newline optionally preceded or followed by spaces
30+
NEWLINE = 'regexp:(\r|\n|\r\n)'
3331

3432
LP='('
3533
RP=')'
@@ -381,7 +379,7 @@ cast_expression ::= type_literal_expression unary_expression
381379

382380
//private attributed_expression ::= type_literal variable
383381

384-
left pipeline_tail ::= ( nls? PIPE nls? command_call_expression )+
382+
left pipeline_tail ::= ( NEWLINE? PIPE nls? command_call_expression )+
385383
{elementType=pipeline}
386384

387385
command_call_expression ::= command_invocation_operator ( (command_module command_name_expr command_element* ) | command_name_expr command_element* ) | command_name_expression command_element*
@@ -793,9 +791,9 @@ if_statement ::= 'if' nls? LP nls? pipeline nls? RP nls? statement_block (nls? e
793791
elseif_clause ::= 'elseif' nls? LP nls? pipeline nls? RP nls? statement_block {pin=1}
794792
else_clause ::= 'else' nls? statement_block {pin=1}
795793

796-
private sep ::= SEMI | NLS | new_line_char | comment //COMMENT //hide psi
794+
private sep ::= SEMI | (NEWLINE space*) | new_line_char | comment //COMMENT //hide psi
797795
private statement_end ::= sep | RCURLY | RP | <<eof>>//ex: parethnisized_expression $AllNodes.Where{$_.Role -eq "WebServer"}
798-
private nls ::= (comment? NLS comment?)+ //NLS
796+
private nls ::= (comment? NEWLINE space* comment?)+
799797
private new_line_char ::= LF
800798

801799
comment ::= !is_id requires_comment | !is_id SINGLE_LINE_COMMENT | DELIMITED_COMMENT

src/main/resources/_PowerShellLexer.flex

+3-4
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ OP_BOR={DASH}[bB]{OR}
159159
EXCL_MARK="!"
160160

161161
NL=(\r|\n|\r\n)
162-
NLS={WHITE_SPACE}*{NL}({NL}|{WHITE_SPACE}*)*
163162
WS_OR_NL={WHITE_SPACE}|{NL}
164163
CH_DQ=(\"|||)
165164
CH_SQ=(\'||||)
@@ -302,12 +301,12 @@ BRACED_VAR_START={DS}{LCURLY}
302301
<VERBATIM_ARGUMENT> {
303302
{VERBATIM_ARG_INPUT} { return VERBATIM_ARG_INPUT; }
304303
"|" { popState(); return PIPE; }
305-
{NLS} { popState(); return NLS; }
304+
{NL} { popState(); return NEWLINE; }
306305
}
307306
<FUNCTION_ID> {
308307
{SIMPLE_ID} { popState(); return SIMPLE_ID; }
309308
{WHITE_SPACE} { return WHITE_SPACE; }
310-
{NLS} { return NLS; }
309+
{NL} { return NEWLINE; }
311310
{GENERIC_ID_PART_TOKENS} { popState(); return GENERIC_ID_PART; }
312311
[^] { popState(); yypushback(yylength()); }
313312
}
@@ -420,7 +419,7 @@ BRACED_VAR_START={DS}{LCURLY}
420419
{OP_OR}/[^a-zA-Z]+{PARAMETER_CHAR}* { return OP_OR; }
421420
{OP_XOR}/[^a-zA-Z]+{PARAMETER_CHAR}* { return OP_XOR; }
422421
{EXCL_MARK} { return EXCL_MARK; }
423-
{NLS} { return NLS; }
422+
{NL} { return NEWLINE; }
424423
{CH_DQ} { pushState(STRING); return DQ_OPEN; }
425424
{VERBATIM_STRING} { return VERBATIM_STRING; }
426425
{EXPANDABLE_HERE_STRING_START} { pushState(HERE_STRING); return EXPANDABLE_HERE_STRING_START; }

0 commit comments

Comments
 (0)