/** * @param array $files * @param boolean $recursive * @return array */ public function detectDeadCode(array $files, $recursive = false) { // Analyse files and collect declared and called functions $analyser = new Analyser(); foreach ($files as $file) { $analyser->analyseFile($file); } // Get info on declared and called functions. $declared = $analyser->getFunctionDeclarations(); $called = $analyser->getFunctionCalls(); $classDescendants = $analyser->getClassDescendants(); // Search for declared, unused functions. $result = array(); foreach ($declared as $name => $source) { if (!isset($called[$name])) { // Unused function/method at first sight. $used = false; // For methods: check calls from subclass instances as well $parts = explode('::', $name); if (count($parts) == 2) { $class = $parts[0]; $subclasses = isset($classDescendants[$class]) ? $classDescendants[$class] : array(); foreach ($subclasses as $subclass) { if (isset($called[$subclass . '::' . $parts[1]])) { $used = true; break; } } } if (!$used) { $result[$name] = $source; } } } if ($recursive) { $done = false; while (!$done) { $done = true; foreach ($called as $callee => $callers) { $_called = false; foreach ($callers as $caller) { if (!isset($result[$caller])) { $_called = true; break; } } if (!$_called) { if (isset($declared[$callee])) { $result[$callee] = $declared[$callee]; } $done = false; unset($called[$callee]); } } } } ksort($result); return $result; }
/** * FileAnalyser constructor * * Validates the given file path and calls the parent's constructor. * * * @param string $file The code to analyse * @param bool $registerNameResolver If set to true `PhpParser\NodeVisitor\NameResolver` will be added as the first * visitor. This may negatively affect performance, some Visitors depend on resolved names, however. * @see \Pvra\RequirementAnalyser::__construct() Base constructor */ public function __construct($file, $registerNameResolver = true) { if (!$this->isFileValid($file)) { throw new \RuntimeException(sprintf('The file "%s" could not be found or accessed.', $file)); } $this->filePath = realpath($file); parent::__construct($registerNameResolver); }
public function __construct($options) { $this->browser = new Browser(); $this->engine = new Engine(); $this->os = new Os(); $this->device = new Device(); parent::__construct($options); }
/** * Short description of method createConditionExpressionFromString * * @access public * @author Joel Bout, <*****@*****.**> * @param string string * @return core_kernel_rules_Expression */ public function createConditionExpressionFromString($string) { $returnValue = null; //test: "IF (11+B_Q01a*3)>=2 AND (B_Q01c=2 OR B_Q01c=7) THEN ^variable := 2*(B_Q01a+7)-^variable"; $question = "if " . $string; // str_replace taken from the MsReader class $question = str_replace("�", "'", $question); // utf8... $question = str_replace("�", "'", $question); // utf8... $question = str_replace("�", "\"", $question); $question = str_replace("�", "\"", $question); try { $analyser = new Analyser(); common_Logger::i('analysing expression \'' . $question . '\''); $tokens = $analyser->analyse($question); } catch (Exception $e) { throw new common_Exception("CapiXML error: {$e->getMessage()}"); } $returnValue = $this->createConditionExpressionFromXML($tokens->getXml()); return $returnValue; }
/** * Shared implementation for parseFile() & parseContents(). * * @param array $tokens The result of a token_get_all() * @param Context $parseContext * @return Analysis */ protected function fromTokens($tokens, $parseContext) { $analyser = new Analyser(); $analysis = new Analysis(); reset($tokens); $token = ''; $imports = ['swg' => 'Swagger\\Annotations']; // Use @SWG\* for swagger annotations (unless overwritten by a use statement) $parseContext->uses = []; $classContext = $parseContext; // Use the parseContext until a classContext is created. $classDefinition = false; $comment = false; $line = 0; $lineOffset = $parseContext->line ?: 0; while ($token !== false) { $previousToken = $token; $token = $this->nextToken($tokens, $parseContext); if (is_array($token) === false) { // Ignore tokens like "{", "}", etc continue; } if ($token[0] === T_DOC_COMMENT) { if ($comment) { // 2 Doc-comments in succession? $analysis->addAnnotations($analyser->fromComment($comment, new Context(['line' => $line], $classContext))); } $comment = $token[1]; $line = $token[2] + $lineOffset; continue; } if ($token[0] === T_ABSTRACT) { $token = $this->nextToken($tokens, $parseContext); // Skip "abstract" keyword } if ($token[0] === T_CLASS) { // Doc-comment before a class? if (is_array($previousToken) && $previousToken[0] === T_DOUBLE_COLON) { //php 5.5 class name resolution (i.e. ClassName::class) continue; } $token = $this->nextToken($tokens, $parseContext); $classContext = new Context(['class' => $token[1], 'line' => $token[2]], $parseContext); if ($classDefinition) { $analysis->addClassDefinition($classDefinition); } $classDefinition = ['class' => $token[1], 'extends' => null, 'properties' => [], 'methods' => [], 'context' => $classContext]; // @todo detect end-of-class and reset $classContext $token = $this->nextToken($tokens, $parseContext); if ($token[0] === T_EXTENDS) { $classContext->extends = $this->parseNamespace($tokens, $token, $parseContext); $classDefinition['extends'] = $classContext->fullyQualifiedName($classContext->extends); } if ($comment) { $classContext->line = $line; $analysis->addAnnotations($analyser->fromComment($comment, $classContext)); $comment = false; continue; } } if ($token[0] == T_STATIC) { $token = $this->nextToken($tokens, $parseContext); if ($token[0] === T_VARIABLE) { // static property $propertyContext = new Context(['property' => substr($token[1], 1), 'static' => true, 'line' => $line], $classContext); if ($classDefinition) { $classDefinition['properties'][$propertyContext->property] = $propertyContext; } if ($comment) { $analysis->addAnnotations($analyser->fromComment($comment, $propertyContext)); $comment = false; } continue; } } if (in_array($token[0], [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR])) { // Scope $token = $this->nextToken($tokens, $parseContext); if ($token[0] == T_STATIC) { $token = $this->nextToken($tokens, $parseContext); } if ($token[0] === T_VARIABLE) { // instance property $propertyContext = new Context(['property' => substr($token[1], 1), 'line' => $line], $classContext); if ($classDefinition) { $classDefinition['properties'][$propertyContext->property] = $propertyContext; } if ($comment) { $analysis->addAnnotations($analyser->fromComment($comment, $propertyContext)); $comment = false; } } elseif ($token[0] === T_FUNCTION) { $token = $this->nextToken($tokens, $parseContext); if ($token[0] === T_STRING) { $methodContext = new Context(['method' => $token[1], 'line' => $line], $classContext); if ($classDefinition) { $classDefinition['methods'][$token[1]] = $methodContext; } if ($comment) { $analysis->addAnnotations($analyser->fromComment($comment, $methodContext)); $comment = false; } } } continue; } elseif ($token[0] === T_FUNCTION) { $token = $this->nextToken($tokens, $parseContext); if ($token[0] === T_STRING) { $methodContext = new Context(['method' => $token[1], 'line' => $line], $classContext); if ($classDefinition) { $classDefinition['methods'][$token[1]] = $methodContext; } if ($comment) { $analysis->addAnnotations($analyser->fromComment($comment, $methodContext)); $comment = false; } } } if (in_array($token[0], [T_NAMESPACE, T_USE]) === false) { // Skip "use" & "namespace" to prevent "never imported" warnings) // Not a doc-comment for a class, property or method? if ($comment) { $analysis->addAnnotations($analyser->fromComment($comment, new Context(['line' => $line], $classContext))); $comment = false; } } if ($token[0] === T_NAMESPACE) { $parseContext->namespace = $this->parseNamespace($tokens, $token, $parseContext); continue; } if ($token[0] === T_USE) { $statements = $this->parseUseStatement($tokens, $token, $parseContext); foreach ($statements as $alias => $target) { if ($target[0] === '\\') { $target = substr($target, 1); } $parseContext->uses[$alias] = $target; foreach (Analyser::$whitelist as $namespace) { if (strcasecmp(substr($target, 0, strlen($namespace)), $namespace) === 0) { $imports[strtolower($alias)] = $target; break; } } } $analyser->docParser->setImports($imports); continue; } } if ($comment) { // File ends with a T_DOC_COMMENT $analysis->addAnnotations($analyser->fromComment($comment, new Context(['line' => $line], $classContext))); } if ($classDefinition) { $analysis->addClassDefinition($classDefinition); } return $analysis; }
function reduce(&$tokens) { $level = 1; $tokenCloseParenthesis = new TokenCloseParenthesis(); $begin = 1 + $tokens->pos($this); // first token after the parenthesis // echo "REDUCE $tokens @$begin\n"; /* * echo "call\n"; print_r($tokens); */ for ($cursor = $begin; $cursor < $tokens->count(); $cursor++) { $token = $tokens->get($cursor); // echo "@ '$token'\n"; // echo "@ ".get_class($token)." - '".get_class($this)."'\n"; if ($token->typeOf($this)) { $level++; // echo "i+\n"; } else { if ($token->typeOf($tokenCloseParenthesis)) { $level--; // echo "i-\n"; } } if (0 == $level) { $begin--; // $begin is at the position of the opening parenthesis $end = $cursor; // $end is at the position of the closing parenthesis // echo "'$begin' '$end'\n"; // $toto = $tokens->subSet($begin, $end); /* * print_r($toto); exit(); */ $analyser = new Analyser(); $subReduce = $analyser->analyse($tokens->subSet($begin + 1, $end - 1)); // exit(); $tokens->delSet($begin, $end, $subReduce); return; } } // TODO: tell which was the opening parenthesis throw new Exception("Closing parenthesis not found"); }
/** * * @param Analysis $analysis * @param Analyser $analyser * @param string $comment * @param Context $context */ private function analyseComment($analysis, $analyser, $comment, $context) { $analysis->addAnnotations($analyser->fromComment($comment, $context), $context); }
/** * Short description of method analyseExpression * * @access public * @author Joel Bout, <*****@*****.**> * @param string expressionInput * @param boolean isCondition * @return DomDocument */ public function analyseExpression($expressionInput, $isCondition = false) { $returnValue = null; //place the following bloc in a helper if (!empty($expressionInput)) { $question = $expressionInput; } else { $question = ""; } //question test: //$question = "IF (11+B_Q01a*3)>=2 AND (B_Q01c=2 OR B_Q01c=7) THEN ^variable := 2*(B_Q01a+7)-^variable"; //analyse the expressionInput string and convert to an XML document: if (get_magic_quotes_gpc()) { $question = stripslashes($question); // Magic quotes are deprecated } //TODO: check if the variables exists and are associated to the process definition $returnValue = null; if (!empty($question)) { // something to parse // str_replace taken from the MsReader class $question = str_replace("�", "'", $question); // utf8... $question = str_replace("�", "'", $question); // utf8... $question = str_replace("�", "\"", $question); $question = str_replace("�", "\"", $question); if ($isCondition) { $question = "if " . $question; } try { $analyser = new Analyser(); common_Logger::i('analysing expression \'' . $question . '\''); $tokens = $analyser->analyse($question); // $xml = htmlspecialchars($tokens->getXmlString(true)); // $xml = $tokens->getXmlString(true); $returnValue = $tokens->getXml(); } catch (Exception $e) { throw new common_Exception("CapiXML error: {$e->getMessage()}"); } } return $returnValue; }
/** * @covers Puml\Analyser::getObject */ public function testGetObject() { $this->assertInstanceOf('\\Puml\\Model\\Object', $this->object->getObject()); }
/** * StringAnalyser constructor * * @param string $string The code to analyse * @param bool $registerNameResolver Inherited from the base class `Analyser` * @see Analyser::__construct() Base Constructor */ public function __construct($string, $registerNameResolver = true) { $this->string = $string; parent::__construct($registerNameResolver); }