Skip to content

Commit 95c842d

Browse files
authored
fix column computation of block strings (#5102)
1 parent 0089ce9 commit 95c842d

File tree

3 files changed

+44
-36
lines changed
  • libraries/apollo-ast/src
    • commonMain/kotlin/com/apollographql/apollo3/ast/internal
    • commonTest/kotlin/com/apollographql/apollo3/graphql/ast/test

3 files changed

+44
-36
lines changed

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/internal/Lexer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ internal class Lexer(val src: String) {
332332
private fun readBlockString(): Token {
333333
val start = pos - 3 // because of """
334334
val startLine = line
335+
val startColumn = column(start)
335336
val blockLines = mutableListOf<String>()
336337
val currentLine = StringBuilder()
337338

@@ -383,7 +384,7 @@ internal class Lexer(val src: String) {
383384

384385
return Token.String(
385386
startLine,
386-
column(start),
387+
startColumn,
387388
line,
388389
column(pos - 1),
389390
blockLines.dedentBlockStringLines().joinToString("\n")

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/internal/Parser.kt

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,8 @@ import com.apollographql.apollo3.ast.GQLValue
4848
import com.apollographql.apollo3.ast.GQLVariableDefinition
4949
import com.apollographql.apollo3.ast.GQLVariableValue
5050
import com.apollographql.apollo3.ast.SourceLocation
51-
import okio.BufferedSource
52-
import okio.Closeable
5351

54-
internal class Parser(src: String, val withSourceLocation: Boolean, val filePath: String?) {
52+
internal class Parser(src: String, private val withSourceLocation: Boolean, val filePath: String?) {
5553
private val lexer = Lexer(src)
5654
private var token = lexer.nextToken()
5755
private var lastToken = token
@@ -292,8 +290,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
292290
return expectToken<Token.Name>().value
293291
}
294292

295-
private fun parseOperationDefinition(): GQLOperationDefinition {
296-
val start = token
293+
private fun parseOperationDefinition(start: Token): GQLOperationDefinition {
297294
val description = expectOptionalToken<Token.String>()?.value
298295

299296
if (peek<Token.LeftBrace>()) {
@@ -384,8 +381,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
384381
)
385382
}
386383

387-
private fun parseSchemaDefinition(): GQLSchemaDefinition {
388-
val start = token
384+
private fun parseSchemaDefinition(start: Token): GQLSchemaDefinition {
389385
val description = parseDescription()
390386

391387
expectKeyword("schema")
@@ -422,8 +418,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
422418
)
423419
}
424420

425-
private fun parseScalarTypeDefinition(): GQLScalarTypeDefinition {
426-
val start = token
421+
private fun parseScalarTypeDefinition(start: Token): GQLScalarTypeDefinition {
427422
val description = parseDescription()
428423
expectKeyword("scalar")
429424
val name = parseName()
@@ -479,8 +474,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
479474
return parseNonEmptyListOrNull<Token.LeftBrace, Token.RightBrace, GQLFieldDefinition>(::parseFieldDefinition).orEmpty()
480475
}
481476

482-
private fun parseObjectTypeDefinition(): GQLTypeDefinition {
483-
val start = token
477+
private fun parseObjectTypeDefinition(start: Token): GQLTypeDefinition {
484478
val description = parseDescription()
485479
this.expectKeyword("type")
486480
val name = parseName()
@@ -520,8 +514,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
520514
)
521515
}
522516

523-
private fun parseInterfaceTypeDefinition(): GQLInterfaceTypeDefinition {
524-
val start = token
517+
private fun parseInterfaceTypeDefinition(start: Token): GQLInterfaceTypeDefinition {
525518
val description = parseDescription()
526519
expectKeyword("interface")
527520
val name = parseName()
@@ -561,8 +554,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
561554
)
562555
}
563556

564-
private fun parseUnionTypeDefinition(): GQLUnionTypeDefinition {
565-
val start = token
557+
private fun parseUnionTypeDefinition(start: Token): GQLUnionTypeDefinition {
566558
val description = parseDescription()
567559
expectKeyword("union")
568560
val name = parseName()
@@ -606,8 +598,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
606598
}
607599
}
608600

609-
private fun parseInputObjectTypeDefinition(): GQLInputObjectTypeDefinition {
610-
val start = token
601+
private fun parseInputObjectTypeDefinition(start: Token): GQLInputObjectTypeDefinition {
611602
val description = parseDescription()
612603
expectKeyword("input")
613604
val name = parseName()
@@ -647,8 +638,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
647638
return parseNonEmptyListOrNull<Token.LeftBrace, Token.RightBrace, GQLInputValueDefinition>(::parseInputValueDefinition).orEmpty()
648639
}
649640

650-
private fun parseEnumTypeDefinition(): GQLEnumTypeDefinition {
651-
val start = token
641+
private fun parseEnumTypeDefinition(start: Token): GQLEnumTypeDefinition {
652642
val description = parseDescription()
653643
expectKeyword("enum")
654644
val name = parseName()
@@ -717,8 +707,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
717707
return name
718708
}
719709

720-
private fun parseDirectiveDefinition(): GQLDirectiveDefinition {
721-
val start = token
710+
private fun parseDirectiveDefinition(start: Token): GQLDirectiveDefinition {
722711
val description = parseDescription()
723712
expectKeyword("directive")
724713
expectToken<Token.At>()
@@ -758,27 +747,27 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
758747
}
759748

760749
private fun parseDefinition(): GQLDefinition {
761-
750+
val start = token
762751
val hasDescription = peek<Token.String>()
763752
val t = if (hasDescription) lookaheadToken() else token
764753

765754
return when (t) {
766-
is Token.LeftBrace -> parseOperationDefinition()
755+
is Token.LeftBrace -> parseOperationDefinition(start)
767756
is Token.Name -> {
768757
if (t.value == "extend" && hasDescription) {
769758
throw ParserException("Type system extensions cannot have a description", t)
770759
}
771760
when (t.value) {
772-
"schema" -> parseSchemaDefinition()
773-
"scalar" -> parseScalarTypeDefinition()
774-
"type" -> parseObjectTypeDefinition()
775-
"interface" -> parseInterfaceTypeDefinition()
776-
"union" -> parseUnionTypeDefinition()
777-
"enum" -> parseEnumTypeDefinition()
778-
"input" -> parseInputObjectTypeDefinition()
779-
"directive" -> parseDirectiveDefinition()
780-
"query", "mutation", "subscription" -> parseOperationDefinition()
781-
"fragment" -> parseFragmentDefinition()
761+
"schema" -> parseSchemaDefinition(start)
762+
"scalar" -> parseScalarTypeDefinition(start)
763+
"type" -> parseObjectTypeDefinition(start)
764+
"interface" -> parseInterfaceTypeDefinition(start)
765+
"union" -> parseUnionTypeDefinition(start)
766+
"enum" -> parseEnumTypeDefinition(start)
767+
"input" -> parseInputObjectTypeDefinition(start)
768+
"directive" -> parseDirectiveDefinition(start)
769+
"query", "mutation", "subscription" -> parseOperationDefinition(start)
770+
"fragment" -> parseFragmentDefinition(start)
782771
"extend" -> parseTypeSystemExtension()
783772
else -> unexpected(t)
784773
}
@@ -788,8 +777,7 @@ internal class Parser(src: String, val withSourceLocation: Boolean, val filePath
788777
}
789778
}
790779

791-
private fun parseFragmentDefinition(): GQLFragmentDefinition {
792-
val start = token
780+
private fun parseFragmentDefinition(start: Token): GQLFragmentDefinition {
793781
val description = parseDescription()
794782
expectKeyword("fragment")
795783
val name = parseFragmentName()

libraries/apollo-ast/src/commonTest/kotlin/com/apollographql/apollo3/graphql/ast/test/LexerTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,4 +631,23 @@ class LexerTest {
631631
assertEquals(6, column)
632632
}
633633
}
634+
635+
@Test
636+
fun blockStringColumn() {
637+
val currentVariantSdl = """
638+
""${'"'}
639+
Directive description
640+
""${'"'}
641+
directive @someDirective(
642+
""${'"'}Argument desedcription""${'"'}
643+
arg1: String @deprecated(reason: "directive on argument")
644+
) repeatable on ENUM | SCHEMA
645+
type Query { fieldA: String }
646+
""".trimIndent()
647+
648+
Lexer(currentVariantSdl).apply {
649+
nextToken()
650+
assertEquals(1, nextToken().column)
651+
}
652+
}
634653
}

0 commit comments

Comments
 (0)