Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.12] Descriptions as strings #242

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Language/AST/DirectiveDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ class DirectiveDefinitionNode extends Node implements TypeSystemDefinitionNode
* @var NameNode[]
*/
public $locations;

/**
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/EnumTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class EnumTypeDefinitionNode extends Node implements TypeDefinitionNode
public $values;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/EnumValueDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class EnumValueDefinitionNode extends Node
public $directives;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/FieldDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class FieldDefinitionNode extends Node
public $directives;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/InputObjectTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class InputObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
public $fields;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/InputValueDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class InputValueDefinitionNode extends Node
public $directives;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/InterfaceTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class InterfaceTypeDefinitionNode extends Node implements TypeDefinitionNode
public $fields = [];

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/ObjectTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
public $fields;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
2 changes: 1 addition & 1 deletion src/Language/AST/ScalarTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ScalarTypeDefinitionNode extends Node implements TypeDefinitionNode
public $directives;

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
5 changes: 5 additions & 0 deletions src/Language/AST/StringValueNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ class StringValueNode extends Node implements ValueNode
* @var string
*/
public $value;

/**
* @var boolean|null
*/
public $block;
}
2 changes: 1 addition & 1 deletion src/Language/AST/UnionTypeDefinitionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class UnionTypeDefinitionNode extends Node implements TypeDefinitionNode
public $types = [];

/**
* @var string
* @var StringValueNode|null
*/
public $description;
}
146 changes: 122 additions & 24 deletions src/Language/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use GraphQL\Error\SyntaxError;
use GraphQL\Utils\Utils;
use GraphQL\Utils\BlockString;

/**
* A Lexer is a stateful stream generator in that every time
Expand Down Expand Up @@ -91,13 +92,18 @@ public function __construct(Source $source, array $options = [])
*/
public function advance()
{
$token = $this->lastToken = $this->token;
$this->lastToken = $this->token;
$token = $this->token = $this->lookahead();
return $token;
}

public function lookahead()
{
$token = $this->token;
if ($token->kind !== Token::EOF) {
do {
$token = $token->next = $this->readToken($token);
$token = $token->next ?: ($token->next = $this->readToken($token));
} while ($token->kind === Token::COMMENT);
$this->token = $token;
}
return $token;
}
Expand Down Expand Up @@ -201,7 +207,15 @@ private function readToken(Token $prev)
->readNumber($line, $col, $prev);
// "
case 34:
return $this->moveStringCursor(-1, -1 * $bytes)
list(,$nextCode) = $this->readChar();
list(,$nextNextCode) = $this->moveStringCursor(1, 1)->readChar();

if ($nextCode === 34 && $nextNextCode === 34) {
return $this->moveStringCursor(-2, (-1 * $bytes) - 1)
->readBlockString($line, $col, $prev);
}

return $this->moveStringCursor(-2, (-1 * $bytes) - 1)
->readString($line, $col, $prev);
}

Expand Down Expand Up @@ -372,10 +386,26 @@ private function readString($line, $col, Token $prev)
while (
$code &&
// not LineTerminator
$code !== 10 && $code !== 13 &&
// not Quote (")
$code !== 34
$code !== 10 && $code !== 13
) {
// Closing Quote (")
if ($code === 34) {
$value .= $chunk;

// Skip quote
$this->moveStringCursor(1, 1);

return new Token(
Token::STRING,
$start,
$this->position,
$line,
$col,
$prev,
$value
);
}

$this->assertValidStringCharacterCode($code, $this->position);
$this->moveStringCursor(1, $bytes);

Expand Down Expand Up @@ -421,27 +451,83 @@ private function readString($line, $col, Token $prev)
list ($char, $code, $bytes) = $this->readChar();
}

if ($code !== 34) {
throw new SyntaxError(
$this->source,
$this->position,
'Unterminated string.'
);
}
throw new SyntaxError(
$this->source,
$this->position,
'Unterminated string.'
);
}

/**
* Reads a block string token from the source file.
*
* """("?"?(\\"""|\\(?!=""")|[^"\\]))*"""
*/
private function readBlockString($line, $col, Token $prev)
{
$start = $this->position;

$value .= $chunk;
// Skip leading quotes and read first string char:
list ($char, $code, $bytes) = $this->moveStringCursor(3, 3)->readChar();

// Skip trailing quote:
$this->moveStringCursor(1, 1);
$chunk = '';
$value = '';

return new Token(
Token::STRING,
$start,
while ($code) {
// Closing Triple-Quote (""")
if ($code === 34) {
// Move 2 quotes
list(,$nextCode) = $this->moveStringCursor(1, 1)->readChar();
list(,$nextNextCode) = $this->moveStringCursor(1, 1)->readChar();

if ($nextCode === 34 && $nextNextCode === 34) {
$value .= $chunk;

$this->moveStringCursor(1, 1);

return new Token(
Token::BLOCK_STRING,
$start,
$this->position,
$line,
$col,
$prev,
BlockString::value($value)
);
} else {
// move cursor back to before the first quote
$this->moveStringCursor(-2, -2);
}
}

$this->assertValidBlockStringCharacterCode($code, $this->position);
$this->moveStringCursor(1, $bytes);

list(,$nextCode, $nextBytes) = $this->readChar();
list(,$nextNextCode, $nextNextBytes) = $this->moveStringCursor(1, 1)->readChar();
list(,$nextNextNextCode, $nextNextNextBytes) = $this->moveStringCursor(1, 1)->readChar();

// Escape Triple-Quote (\""")
if ($code === 92 &&
$nextCode === 34 &&
$nextNextCode === 34 &&
$nextNextNextCode === 34
) {
$this->moveStringCursor(1, 1);
$value .= $chunk . '"""';
$chunk = '';
} else {
$this->moveStringCursor(-2, -2);
$chunk .= $char;
}

list ($char, $code, $bytes) = $this->readChar();
}

throw new SyntaxError(
$this->source,
$this->position,
$line,
$col,
$prev,
$value
'Unterminated string.'
);
}

Expand All @@ -457,6 +543,18 @@ private function assertValidStringCharacterCode($code, $position)
}
}

private function assertValidBlockStringCharacterCode($code, $position)
{
// SourceCharacter
if ($code < 0x0020 && $code !== 0x0009 && $code !== 0x000A && $code !== 0x000D) {
throw new SyntaxError(
$this->source,
$position,
'Invalid character within String: ' . Utils::printCharCode($code)
);
}
}

/**
* Reads from body starting at startPosition until it finds a non-whitespace
* or commented character, then places cursor to the position of that character.
Expand Down
Loading