コード例 #1
0
 public function instrumentFile($sourceFile)
 {
     if ($this->manifest === NULL) {
         $this->manifest = $this->kernel->getManifest();
     }
     $parsedFile = $this->manifest->getFile($sourceFile);
     $storage = $parsedFile->getStorage();
     $generator = new SourceGenerator($parsedFile->getBuffer());
     foreach ($storage->getTypes() as $parsedType) {
         $fields = $storage->getFields($parsedType);
         $methods = $storage->getMethods($parsedType);
         $typeInfo = new ParsedTypeInfo($parsedType, $fields, $methods);
         $instrumentation = new Instrumentation($this->manifest);
         $instrumentation->introduceInterface('KoolKode\\K2\\Instrument\\KoolTypeInterface');
         if ($typeInfo->isClass()) {
             // Introduce instance type LSB marker:
             $instrumentation->introduceCode('protected static $K2TypeName = __CLASS__;');
             // Introduce helper method trait:
             $instrumentation->introduceTrait('KoolKode\\K2\\Instrument\\KoolTypeTrait');
             // Implement original source file lookup:
             $introduced = ' public static function K2GetSourceFile() { return ';
             $introduced .= var_export($sourceFile, true) . '; }';
             $instrumentation->introduceCode($introduced);
             // Implement namespace context lookup:
             $introduced = ' public static function K2GetNamespaceContext() { ';
             $introduced .= 'static $ctx; if($ctx === NULL) { ';
             $introduced .= '$ctx = ' . $typeInfo->getNamespaceContext()->compile() . '; ';
             $introduced .= '} return $ctx; }';
             $instrumentation->introduceCode($introduced);
             // Extended class introduction:
             $extends = $parsedType->getExtends();
             if (!empty($extends)) {
                 $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_SUPERCLASS, '\\' . array_shift($extends));
             }
             $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_PREPENDED_CODE, ' if(!class_exists(' . var_export($parsedType->getName(), true) . ', false)) { ');
         } elseif ($typeInfo->isInterface()) {
             $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_EXTENDS, implode(', ', $parsedType->getExtends()));
             $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_PREPENDED_CODE, ' if(!interface_exists(' . var_export($parsedType->getName(), true) . ', false)) { ');
         } elseif ($typeInfo->isTrait()) {
             $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_PREPENDED_CODE, ' if(!trait_exists(' . var_export($parsedType->getName(), true) . ', false)) { ');
         }
         foreach ($this->instrumentors as $instrumentor) {
             $instrumentor->instrument($typeInfo, $instrumentation);
         }
         if ($instrumentation->hasInitializationCode()) {
             $this->buildConstructor($typeInfo, $instrumentation);
         }
         $traits = $instrumentation->getIntroducedTraits();
         $traitCode = empty($traits) ? '' : 'use ' . implode(', ', $traits) . '; ';
         $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_NAME, $typeInfo->getLocalName());
         $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_INTERFACES, implode(', ', $instrumentation->getIntroducedInterfaces()));
         $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_CODE, $traitCode . $instrumentation->getIntroducedCode());
         $generator->populateTypeMarker($parsedType, ParsedType::MARKER_INTRODUCED_EXTERNAL_CODE, ' } ' . $instrumentation->getAppendedCode());
         foreach ($typeInfo->getMethods() as $methodInfo) {
             $methodIns = $instrumentation->getMethodInstrumentation($methodInfo);
             if ($methodIns->count()) {
                 $generator->populateMethodMarker($parsedType, $methodInfo->getParsedMethod(), ParsedMethod::MARKER_PREPENDED_CODE, $methodIns->getPrependedCode());
                 $generator->populateMethodMarker($parsedType, $methodInfo->getParsedMethod(), ParsedMethod::MARKER_APPENDED_CODE, $methodIns->getAppendedCode());
             }
         }
     }
     return $generator->generateCode($sourceFile, dirname($sourceFile));
 }
コード例 #2
0
ファイル: SqliteManifest.php プロジェクト: koolkode/k2
 public function parseFile($file, $key = NULL)
 {
     $mtime = filemtime($file);
     $hash = md5($file) . dechex(strlen($file));
     $sql = 'SELECT * FROM "meta_file" WHERE "hash" = :hash AND "mtime" >= :mtime LIMIT 1';
     $stmt = $this->pdo->prepare($sql);
     $stmt->bindValue('hash', $hash);
     $stmt->bindValue('mtime', $mtime);
     $stmt->execute();
     $row = $stmt->fetch(\PDO::FETCH_ASSOC);
     if ($row !== false) {
         return new MetaFile($row['hash'], $row['location'], $row['mtime'], unserialize(gzdecode($row['storage'])), unserialize(gzdecode($row['buffer'])));
     }
     $storage = new ArraySourceStorage();
     $parser = new SourceParser();
     $buffer = $parser->parse(SourceStream::fromUrl($file), $storage);
     $this->insertFileStmt->execute(['hash' => $hash, 'location' => $file, 'mtime' => $mtime, 'key' => $key, 'storage' => gzencode(serialize($storage), 1), 'buffer' => gzencode(serialize($buffer), 1)]);
     foreach ($storage->getTypes() as $type) {
         $typeInfo = new ParsedTypeInfo($type, [], []);
         $this->insertTypeStmt->execute(['name' => $typeInfo->getName(), 'file' => $hash, 'mod' => MetaInfo::getTypeModifiers($typeInfo), 'mtime' => $mtime, 'data' => gzencode(serialize($type), 1)]);
         foreach ($type->getSupertypes() as $supertype) {
             $this->insertSupertypeStmt->execute(['super' => $supertype, 'sub' => $typeInfo->getName()]);
         }
         foreach ($typeInfo->getAnnotationCandidates() as $anno) {
             $this->insertTypeAnnotationStmt->execute(['type' => $typeInfo->getName(), 'anno' => $anno]);
         }
         foreach ($storage->getFields($type) as $field) {
             $fieldInfo = new ParsedFieldInfo($typeInfo, $field);
             $this->insertFieldStmt->execute(['type' => $type->getName(), 'field' => $fieldInfo->getName(), 'mod' => MetaInfo::getFieldModifiers($fieldInfo)]);
             foreach ($fieldInfo->getAnnotationCandidates() as $anno) {
                 $this->insertFieldAnnotationStmt->execute(['type' => $typeInfo->getName(), 'field' => $field->getName(), 'anno' => $anno]);
             }
         }
         foreach ($storage->getMethods($type) as $method) {
             $methodInfo = new ParsedMethodInfo($typeInfo, $method);
             $this->insertMethodStmt->execute(['type' => $type->getName(), 'method' => $methodInfo->getName(), 'mod' => MetaInfo::getMethodModifiers($methodInfo)]);
             foreach ($methodInfo->getAnnotationCandidates() as $anno) {
                 $this->insertMethodAnnotationStmt->execute(['type' => $type->getName(), 'method' => $methodInfo->getName(), 'anno' => $anno]);
             }
         }
         $comment = new DocComment($type->getComment());
         foreach ($comment->getTagValues('merge') as $group) {
             $this->insertMergeGroupStmt->execute(['type' => $typeInfo->getName(), 'group' => trim($group)]);
         }
         $this->typeCache[strtolower($type->getName())] = new ParsedTypeInfo($type, $storage->getFields($type), $storage->getMethods($type));
     }
     return new MetaFile($hash, $file, $mtime, $storage, $buffer);
 }