Example #1
0
 /**
  * Parse a class from token reader
  *
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Routine\Func
  */
 public function parseClass(\vc\Tokens\Access $access)
 {
     $token = $access->findRequired(array(Token::T_CLASS, Token::T_ABSTRACT));
     $class = new \vc\Data\Type\Cls($token->getLine(), $access->getComment());
     // Extract the abstract flag from the class definition
     if ($token->is(Token::T_ABSTRACT)) {
         $class->setAbstract(TRUE);
         $access->findRequired(array(Token::T_CLASS));
     }
     // Searches for the name of the class
     $token = $access->findRequired(array(Token::T_STRING));
     // Set the name of the class
     $class->setName($token->getContent());
     // Look for parent classes and interfaces
     $token = $access->findRequired(array(Token::T_EXTENDS, Token::T_IMPLEMENTS, Token::T_CURLY_OPEN));
     // Add the parent class
     if ($token->is(Token::T_EXTENDS)) {
         $class->setExtends($this->path->parsePath($access));
         // Look for any interfaces
         $token = $access->findRequired(array(Token::T_IMPLEMENTS, Token::T_CURLY_OPEN));
     }
     // Add any interface implementations
     if ($token->is(Token::T_IMPLEMENTS)) {
         $class->setIFaces($this->pathList->parsePathList($access));
         $access->findRequired(array(Token::T_CURLY_OPEN));
     }
     // Finally, parse out the content of the class
     $this->members->parseMembers($class, $access);
     return $class;
 }
Example #2
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Data\Signature $signature The signature to use as a source
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Property
  */
 public function parseProperty(\vc\Data\Signature $signature, \vc\Tokens\Access $access)
 {
     $prop = $signature->buildProperty();
     // Keep looking for modifier tokens until we reach the variable.
     // This isn't as strict as it could be about token order, but it greatly
     // simplifies the method to do it like this.
     do {
         $token = $access->findRequired(array(Token::T_STATIC, Token::T_VAR, Token::T_VARIABLE, Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE));
         if ($token->is(array(Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE))) {
             $prop->setVisibility(\vc\Data\Visibility::fromToken($token));
         } else {
             if ($token->is(Token::T_STATIC)) {
                 $prop->setStatic(TRUE);
             }
         }
     } while (!$token->is(Token::T_VARIABLE));
     $prop->setName($token->getContent());
     $token = $access->findRequired(array(Token::T_SEMICOLON, Token::T_EQUALS));
     // Look for any default value
     if ($token->is(Token::T_EQUALS)) {
         $prop->setValue($this->value->parseValue($access));
         $access->findRequired(array(Token::T_SEMICOLON));
     }
     return $prop;
 }
Example #3
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Data\Object\Cls $class The class to fill with data
  * @param \vc\Tokens\Access $access The token access
  * @return NULL
  */
 public function parseSignature(\vc\Data\Type\Cls $class, \vc\Tokens\Access $access)
 {
     $sig = new \vc\Data\Signature($access->peekAtToken()->getLine(), $access->getComment());
     // Keep collecting tokens until we find one that differentiates this
     // signature between a method and a property. This isn't as strict
     // as it could be, but it's already complex
     while (TRUE) {
         $token = $access->peekToRequired(array(Token::T_STATIC, Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE, Token::T_ABSTRACT, Token::T_FINAL, Token::T_FUNCTION, Token::T_VAR, Token::T_VARIABLE));
         // These tokens denote a definite method
         if ($token->is(array(Token::T_ABSTRACT, Token::T_FINAL, Token::T_FUNCTION))) {
             $class->addMethod($this->methods->parseMethod($sig, $access));
             return;
         } else {
             if ($token->is(array(Token::T_VAR, Token::T_VARIABLE))) {
                 $class->addProperty($this->properties->parseProperty($sig, $access));
                 return;
             } else {
                 if ($token->is(array(Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE))) {
                     $sig->setVisibility(\vc\Data\Visibility::fromToken($token));
                 } else {
                     if ($token->is(Token::T_STATIC)) {
                         $sig->setStatic(TRUE);
                     }
                 }
             }
         }
         // By this point, we have already determined that this token isn't
         // needed downstream, so we can pop it safely
         $access->popToken();
     }
 }
Example #4
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Data\Signature $signature The base data from which to build
  *      the method
  * @param \vc\Tokens\Access $access The token stream
  * @return \vc\Data\Routine\Method
  */
 public function parseMethod(\vc\Data\Signature $signature, \vc\Tokens\Access $access)
 {
     $method = $signature->buildMethod();
     // Continue iterating until we encounter a Function token
     while (TRUE) {
         $token = $access->peekToRequired(array(Token::T_STATIC, Token::T_ABSTRACT, Token::T_FINAL, Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE, Token::T_FUNCTION));
         // We don't want to consume the function token because the routine
         // parser looks for it. Break before we get a chance to pop it off
         // the stream
         if ($token->is(Token::T_FUNCTION)) {
             break;
         }
         $access->popToken();
         if ($token->is(array(Token::T_PUBLIC, Token::T_PROTECTED, Token::T_PRIVATE))) {
             $method->setVisibility(\vc\Data\Visibility::fromToken($token));
         } else {
             if ($token->is(Token::T_STATIC)) {
                 $method->setStatic(TRUE);
             } else {
                 if ($token->is(Token::T_ABSTRACT)) {
                     $method->setAbstract(TRUE);
                 } else {
                     if ($token->is(Token::T_FINAL)) {
                         $method->setFinal(TRUE);
                     }
                 }
             }
         }
     }
     $this->routine->parseRoutine($method, $access);
     return $method;
 }
Example #5
0
 /**
  * Parse a function out of the given token reader
  *
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Routine\Func
  */
 public function parseFunc(\vc\Tokens\Access $access)
 {
     $token = $access->peekToRequired(array(Token::T_FUNCTION));
     $func = new \vc\Data\Routine\Func($token->getLine(), $access->getComment());
     $this->routine->parseRoutine($func, $access);
     return $func;
 }
Example #6
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Constant Returns the created constant
  */
 public function parseConstant(\vc\Tokens\Access $access)
 {
     $access->findRequired(array(Token::T_CONST));
     $name = $access->findRequired(array(Token::T_STRING));
     $const = new \vc\Data\Constant($name->getContent());
     $access->findRequired(array(Token::T_EQUALS));
     $const->setValue($this->value->parseValue($access));
     $access->findRequired(array(Token::T_SEMICOLON));
     return $const;
 }
Example #7
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Alias Returns the created alias
  */
 public function parseAlias(\vc\Tokens\Access $access)
 {
     $access->findRequired(array(Token::T_USE));
     $alias = new \vc\Data\Alias($this->path->parsePath($access));
     $as = $access->find(array(Token::T_AS));
     if ($as) {
         $alias->setAlias($this->path->parsePath($access));
     }
     $access->findRequired(array(Token::T_SEMICOLON));
     return $alias;
 }
Example #8
0
 public function testParseProperty_defaultValue()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAPublic->thenSomeSpace->thenAVariable('$var')->thenSomeSpace->thenAnEquals->thenAnInteger(789)->thenASemicolon);
     $sig = new \vc\Data\Signature(120, new \vc\Data\Comment('Note'));
     $this->assertEquals(r8(new \vc\Data\Property(120, new \vc\Data\Comment('Note')))->setName('$var')->setValue(new \vc\Data\Value(789, 'int')), $this->getPropertyParser()->parseProperty($sig, $access));
     $this->assertEndOfTokens($access);
 }
Example #9
0
 public function testParseConstant_Heredoc()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAConst->thenSomeSpace->thenAName('NAME')->thenSomeSpace->thenAnEquals->thenSomeSpace->thenAHereDoc('contents')->thenASemicolon->thenAClass);
     $parser = $this->getConstantParser();
     $this->assertEquals(r8(new \vc\Data\Constant('NAME'))->setValue(new \vc\Data\Value('contents', 'string')), $parser->parseConstant($access));
     $this->assertHasToken(Token::T_CLASS, $access);
 }
Example #10
0
 /**
  * Parses the given token reader
  *
  * @param \r8\FileSys\File $path The file to parse
  * @return \vc\Data\File
  */
 public function parse(\r8\FileSys\File $path)
 {
     $file = new \vc\Data\File($path->getPath());
     $tokens = \vc\Tokens\Access::buildAccess(new \vc\Tokens\Parser(new \r8\Stream\In\File($path)));
     $this->comment->parse($file, $tokens);
     return $file;
 }
Example #11
0
 public function testUntilBlockEnds()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAFunction->thenACloseBlock->thenAClass);
     $until = $access->untilBlockEnds();
     $this->assertThat($until, $this->isInstanceOf('\\vc\\Tokens\\Access'));
     $this->assertHasToken(Token::T_FUNCTION, $until);
     $this->assertEndOfTokens($until);
 }
Example #12
0
 public function testNoCommentFound()
 {
     $reader = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAnOpenTag->thenSomeSpace->thenAClass->thenADocComment('This is a file comment'));
     $parser = new \vc\Parser\File\Comment(new \vc\Parser\Comment(), $this->getStub('vc\\Parser\\File\\NSpaces'));
     $file = new \vc\Data\File('file.php');
     $parser->parse($file, $reader);
     $this->assertEquals(new \vc\Data\Comment(), $file->getComment());
 }
Example #13
0
 public function testParseAnonymousFunc_ReturnsReference()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAFunction->thenSomeSpace->thenAnAmpersand->thenOpenParens->thenCloseParens->thenASemicolon);
     $routine = $this->getMockForAbstractClass('\\vc\\Data\\Routine', array(1));
     $this->getFuncParser()->parseRoutine($routine, $access);
     $this->assertNull($routine->getName());
     $this->assertTrue($routine->getReturnRef());
     $this->assertEndOfTokens($access);
 }
Example #14
0
 public function testParseIFace_Constant()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAConst->thenAName('CONST')->thenAnEquals->thenAnInteger(123)->thenASemicolon);
     $iface = new \vc\Data\Type\IFace(1);
     $parser = new \vc\Parser\IFace\Members(new \vc\Parser\Constant(new \vc\Parser\Value(new \vc\Parser\Brackets(), new \vc\Parser\Path())), $this->getStub('\\vc\\Parser\\Routine\\Method'));
     $parser->parseMembers($iface, $access);
     $this->assertEquals(1, count($iface->getConstants()));
     $this->assertEndOfTokens($access);
 }
Example #15
0
 public function testParse_MultipleSemicolonNamespaceDefinitions()
 {
     $file = new \vc\Data\File('path.php');
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenANamespace('sub\\sub2')->thenASemicolon->thenAFunction->thenANamespace('ns2')->thenASemicolon->thenAFunction);
     $parser = new \vc\Parser\File\NSpaces(new \vc\Parser\Path(), $this->getNSpaceParser(2));
     $parser->parse($file, $access);
     $this->assertEquals(array(new \vc\Data\NSpace('sub\\sub2'), new \vc\Data\NSpace('ns2')), $file->getNamespaces());
     $this->assertEndOfTokens($access);
 }
Example #16
0
 public function testParseAlias_MissingSemicolon()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAUse->thenSomeSpace->thenANamespacePath('sub1\\sub2')->thenSomeSpace->then(Token::T_AS, 'as')->thenSomeSpace->thenAName('renamed'));
     $parser = new \vc\Parser\NSpace\Alias(new \vc\Parser\Path());
     try {
         $parser->parseAlias($access);
         $this->fail("An expected exception was not thrown");
     } catch (\vc\Tokens\Exception\UnexpectedEnd $err) {
     }
 }
Example #17
0
 public function testParseConstant()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAConst);
     $constant = new \vc\Data\Constant('CONST');
     $constParser = $this->getStub('\\vc\\Parser\\Constant');
     $constParser->expects($this->once())->method("parseConstant")->with($this->isInstanceOf('\\vc\\Tokens\\Access'))->will($this->returnCallback(function ($access) use($constant) {
         $access->popToken();
         return $constant;
     }));
     $sigParser = $this->getStub('\\vc\\Parser\\Object\\Signature');
     $sigParser->expects($this->never())->method("parseSignature");
     $class = new \vc\Data\Type\Cls(1);
     $parser = new \vc\Parser\Object\Members($constParser, $sigParser);
     $parser->parseMembers($class, $access);
     $this->assertSame(array($constant), $class->getConstants());
     $this->assertEndOfTokens($access);
 }
Example #18
0
 /**
  * Parse a function out of the given token reader
  *
  * @param \vc\Data\Routine $routine The object to fill with data
  * @param \vc\Tokens\Access $access The token access
  * @return NULL
  */
 public function parseRoutine(\vc\Data\Routine $routine, \vc\Tokens\Access $access)
 {
     $access->findRequired(array(Token::T_FUNCTION));
     $token = $access->peekToRequired(array(Token::T_STRING, Token::T_AMPERSAND, Token::T_PARENS_OPEN));
     // Handle routines that return a reference
     if ($token->is(Token::T_AMPERSAND)) {
         $routine->setReturnRef(TRUE);
         $access->popToken();
         $token = $access->peekToRequired(array(Token::T_STRING, Token::T_PARENS_OPEN));
     }
     // Names are optional because of anonymous methods
     if ($token->is(Token::T_STRING)) {
         $access->popToken();
         $routine->setName($token->getContent());
     }
     $routine->setArgs($this->args->parseArgs($access));
     $access->findRequired(array(Token::T_CURLY_OPEN, Token::T_SEMICOLON));
     $this->brackets->parseCurlies($access);
 }
Example #19
0
 /**
  * Parse an interface from token reader
  *
  * @param \vc\Tokens\Access $access The token access
  * @return \vc\Data\Routine\Func
  */
 public function parseIFace(\vc\Tokens\Access $access)
 {
     $token = $access->findRequired(array(Token::T_INTERFACE));
     $iface = new \vc\Data\Type\IFace($token->getLine(), $access->getComment());
     // Searches for the name of the interface
     $token = $access->findRequired(array(Token::T_STRING));
     $iface->setName($token->getContent());
     // Look for any interfaces that this one extends
     $token = $access->findRequired(array(Token::T_EXTENDS, Token::T_CURLY_OPEN));
     if ($token->is(Token::T_EXTENDS)) {
         $iface->setExtends($this->pathList->parsePathList($access));
         $access->findRequired(array(Token::T_CURLY_OPEN));
     }
     // Finally, parse out the content of the class
     $this->members->parseMembers($iface, $access);
     return $iface;
 }
Example #20
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Data\NSpace $nspace The namespace to parse data into
  * @param \vc\Tokens\Search $access The token access
  * @return NULL
  */
 public function parseNSpace(\vc\Data\NSpace $nspace, \vc\Tokens\Access $access)
 {
     $last = NULL;
     // Keep looking until we have consumed all the tokens in this namespace
     while (TRUE) {
         $token = $access->peekToSkipping(array(Token::T_CLASS, Token::T_ABSTRACT, Token::T_CONST, Token::T_INTERFACE, Token::T_FUNCTION, Token::T_USE));
         if (!$token) {
             break;
         }
         if ($token === $last) {
             throw new \RuntimeException('Possible Infinite Loop Detected. ' . 'Current token has already been parsed');
         }
         $last = $token;
         if ($token->is(array(Token::T_CLASS, Token::T_ABSTRACT))) {
             $nspace->addType($this->object->parseClass($access));
         } else {
             if ($token->is(Token::T_FUNCTION)) {
                 $func = $this->func->parseFunc($access);
                 // Anonymous functions have a very limited scope, so we don't
                 // care about documenting them
                 if (!$func->isAnonymous()) {
                     $nspace->addFunction($func);
                 }
             } else {
                 if ($token->is(Token::T_INTERFACE)) {
                     $nspace->addType($this->iface->parseIFace($access));
                 } else {
                     if ($token->is(Token::T_CONST)) {
                         $nspace->addConstant($this->constant->parseConstant($access));
                     } else {
                         if ($token->is(Token::T_USE)) {
                             $nspace->addAlias($this->alias->parseAlias($access));
                         }
                     }
                 }
             }
         }
     }
 }
Example #21
0
 public function testParseNSpace_Many()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAnInterface->thenAClass->thenAConst->thenAFunction);
     $nspace = new \vc\Data\NSpace(1);
     $this->getNSpaceParser()->parseNSpace($nspace, $access);
     $this->assertEquals(2, count($nspace->getTypes()));
     $this->assertEquals(1, count($nspace->getConstants()));
     $this->assertEquals(1, count($nspace->getFunctions()));
     $this->assertEndOfTokens($access);
 }
Example #22
0
 public function testParsePathList_ThreePaths()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenSomeSpace->thenANamespacePath('path\\to\\cls')->thenAComma->thenSomeSpace->thenANamespacePath('AnObject')->thenAComma->thenSomeSpace->thenANamespacePath('\\stdClass')->thenSomeSpace->thenAnOpenBlock);
     $this->assertEquals(array('path\\to\\cls', 'AnObject', '\\stdClass'), $this->getPathListParser()->parsePathList($access));
 }
Example #23
0
 /**
  * Parses a list of method arguments
  *
  * @param \vc\Tokens\Access $access
  * @return Array
  */
 public function parseArgs(\vc\Tokens\Access $access)
 {
     $access->findRequired(array(Token::T_PARENS_OPEN));
     $args = array();
     // Continue parsing until we hit a close parenthesis
     while (TRUE) {
         $type = $access->peekToRequired(array(Token::T_ARRAY, Token::T_STRING, Token::T_NS_SEPARATOR, Token::T_AMPERSAND, Token::T_VARIABLE, Token::T_PARENS_CLOSE));
         if ($type->is(Token::T_PARENS_CLOSE)) {
             break;
         }
         $args[] = $this->parseArg($access);
     }
     $access->popToken();
     return $args;
 }
Example #24
0
 /**
  * Parses the given token reader
  *
  * @param \vc\Data\File $file The file to parse data into
  * @param \vc\Tokens\Access $access The token access
  * @return NULL
  */
 public function parse(\vc\Data\File $file, \vc\Tokens\Access $access)
 {
     while ($access->hasToken()) {
         $nspace = new \vc\Data\NSpace();
         // If we can't find a namespace, then we are in the global scope
         if ($this->findNS($access)) {
             $inner = $this->buildNS($nspace, $access);
         } else {
             $inner = $access->untilTokens(array(Token::T_NAMESPACE));
         }
         $file->addNamespace($nspace);
         $this->nspace->parseNSpace($nspace, $inner);
     }
 }
Example #25
0
 public function testParseMethod_AbstractPrivateMethod()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenAnAbstract->thenSomeSpace->thenAPrivate->thenSomeSpace->thenAFunction->thenSomeSpace->thenAName('MyFunc')->thenOpenParens->thenCloseParens->thenAnOpenBlock->thenACloseBlock);
     $sig = new \vc\Data\Signature(123);
     $this->assertEquals(r8(new \vc\Data\Routine\Method(123))->setName('MyFunc')->setAbstract(TRUE)->setVisibility(\vc\Data\Visibility::vPrivate()), $this->getMethodParser()->parseMethod($sig, $access));
 }
Example #26
0
 public function testParseArgs_Combined()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenOpenParens->thenANamespacePath('\\path\\to\\class')->thenSomeSpace->thenAnAmpersand->thenSomeSpace->thenAVariable('$test')->thenSomeSpace->thenAnEquals->thenSomeSpace->thenAnInteger(123)->thenAComma->thenAnArray->thenSomeSpace->thenAnAmpersand->thenSomeSpace->thenAVariable('$test2')->thenSomeSpace->thenAnEquals->thenSomeSpace->thenAnArrayValue(array(1))->thenCloseParens);
     $this->assertEquals(array(\r8(new \vc\Data\Arg())->setType('\\path\\to\\class')->setReference(TRUE)->setVariable('$test')->setDefault(new \vc\Data\Value(123, 'int')), \r8(new \vc\Data\Arg())->setType('array')->setReference(TRUE)->setVariable('$test2')->setDefault(new \vc\Data\Value('array( 0 => 1,)', 'array'))), $this->getArgParser()->parseArgs($access));
     $this->assertEndOfTokens($access);
 }
Example #27
0
 /**
  * Parses a value from a token stream
  *
  * @param \vc\Tokens\Access $access
  * @return \vc\Data\Value
  */
 public function parseValue(\vc\Tokens\Access $access)
 {
     $token = $access->peekToRequired(array(Token::T_LNUMBER, Token::T_DNUMBER, Token::T_STRING, Token::T_START_HEREDOC, Token::T_CONSTANT_ENCAPSED_STRING, Token::T_ARRAY, Token::T_MINUS, Token::T_NS_SEPARATOR), array(Token::T_EQUALS));
     switch ($token->getType()) {
         // Strings
         case Token::T_CONSTANT_ENCAPSED_STRING:
             $access->popToken();
             return $this->parseString($token);
             // HereDocs
         // HereDocs
         case Token::T_START_HEREDOC:
             $access->popToken();
             return $this->parseHereDoc($access);
             // Negative numbers
         // Negative numbers
         case Token::T_MINUS:
             $access->popToken();
             $token = $access->findRequired(array(Token::T_LNUMBER, Token::T_DNUMBER));
             return $this->parseNumber(FALSE, $token);
             // Positive Numbers
         // Positive Numbers
         case Token::T_LNUMBER:
         case Token::T_DNUMBER:
             $access->popToken();
             return $this->parseNumber(TRUE, $token);
             // Keywords like true, false, null and relative constants
         // Keywords like true, false, null and relative constants
         case Token::T_STRING:
             return $this->parseKeyword($access, $token);
             // Absolute Constants
         // Absolute Constants
         case Token::T_NS_SEPARATOR:
             return $this->parseConstant($access);
             // Arrays
         // Arrays
         case Token::T_ARRAY:
             $access->popToken();
             return $this->parseArray($access);
         default:
             throw new \RuntimeException("Unexpected Type");
     }
 }
Example #28
0
 public function testParseValue_ClassConstant()
 {
     $access = \vc\Tokens\Access::buildAccess($this->oneTokenReader()->thenSomeSpace->thenAnEquals->thenSomeSpace->thenANamespacePath('\\path')->then(Token::T_DOUBLE_COLON, '::')->thenAName('CONSTANT'));
     $parser = $this->getValueParser();
     $this->assertEquals(new \vc\Data\Value('\\path::CONSTANT', 'constant'), $parser->parseValue($access));
     $this->assertEndOfTokens($access);
 }