- This is a simulated error: VendorName\snippet
+ This is a simulated error: VendorName\snippet
- Location
- .../snippet.php:50
- Type
+ Location
+ .../snippet.php :50
+ Type
E_RECOVERABLE_ERROR
- Error Class
- Error
- Error Code
+ Error Class
+ Error
+ Error Code
1
This is the reason
- Location
- .../snippet.php:53
- Type
+ Location
+ .../snippet.php :53
+ Type
E_RECOVERABLE_ERROR
- Error Class
- Exception
- Error Code
+ Error Class
+ Exception
+ Error Code
0
diff --git a/dist/stonetable/lib/php-code-test-suite/Autoload.php b/dist/stonetable/lib/php-code-test-suite/Autoload.php
index 1d77ea6..ddcaeb3 100644
--- a/dist/stonetable/lib/php-code-test-suite/Autoload.php
+++ b/dist/stonetable/lib/php-code-test-suite/Autoload.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/Debugger/Debugger.php b/dist/stonetable/lib/php-code-test-suite/Debugger/Debugger.php
index b6bc11c..825ba5a 100644
--- a/dist/stonetable/lib/php-code-test-suite/Debugger/Debugger.php
+++ b/dist/stonetable/lib/php-code-test-suite/Debugger/Debugger.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -168,11 +168,11 @@ public function traceDataToCompactLine(
if( $format ) {
- $result .= sprintf(
- '%s ',
- ( $trace_data['class']
- ?? $formatter->shortenPathname($filename) )
- );
+ $result .= ( isset($trace_data['class']) )
+ ? $formatter->formatClassNameOrNamespace($trace_data['class'])
+ : $formatter::formatPathnameAddWrappers(
+ $formatter->shortenPathname($filename)
+ );
} else {
@@ -180,6 +180,7 @@ public function traceDataToCompactLine(
}
if( !isset($trace_data['class']) && $trace_data['line'] ) {
+
$result .= ( $format )
? sprintf(
':%d '
@@ -190,22 +191,34 @@ public function traceDataToCompactLine(
}
$result .= ( $trace_data['type'] ?? ' ' );
- $result .= ( $format )
- ? sprintf(
- '%s'
- . '( '
- . ') '
- . ' ',
- $trace_data['function']
- )
- : ($trace_data['function'] . '()');
+
+ if( $format ) {
+
+ $separator_pos = strrpos($trace_data['function'], '\\');
+
+ if( $separator_pos === false ) {
+ $result .= $this->formatter->formatSimplifiedFunctionStr(
+ $trace_data['function']
+ );
+ } else {
+ $result .= $this->formatter->formatNamespaceName(
+ $trace_data['function'],
+ ['func']
+ ) . '( '
+ . ') ';
+ }
+
+ } else {
+
+ $result .= ($trace_data['function'] . '()');
+ }
if( $format && $convert_links ) {
$result = $formatter->buildIdeHtmlLink(
$filename,
$result,
- ((int)$trace_data['line'] ?? null),
+ ( (int)$trace_data['line'] ?? null ),
class_names: ['file']
);
}
@@ -225,12 +238,19 @@ class_names: ['file']
if( is_object($arg) ) {
+ $class = $arg::class;
+ $formatted_class = $formatter->formatClassNameOrNamespace(
+ $class
+ );
$argument = ( $convert_links )
- ? $formatter->namespaceToIdeHtmlLink($arg::class)
- : $arg::class;
+ ? $formatter->namespaceToIdeHtmlLink(
+ $class,
+ text: $formatted_class
+ )
+ : $formatted_class;
if( !$argument ) {
- $argument = $arg::class;
+ $argument = $formatted_class;
}
$allow_html_entities = false;
@@ -238,7 +258,7 @@ class_names: ['file']
/* Don't attempt to export and show text for the following
types, eg. `var_export` will fail on large arrays containing
objects with circular reference, etc. */
- } elseif( is_array($arg) && is_resource($arg) ) {
+ } elseif( is_array($arg) || is_resource($arg) ) {
$argument = '';
@@ -249,11 +269,11 @@ class_names: ['file']
// String (can be file path or namespace name).
if(
- str_starts_with($argument, '\'')
- && str_ends_with($argument, '\'')
+ str_starts_with($argument, "'")
+ && str_ends_with($argument, "'")
) {
- $trimmed_arg = trim($argument, '\'');
+ $trimmed_arg = trim($argument, "'");
$length = strlen($trimmed_arg);
if( $formatter->isQualifiedPathname($trimmed_arg) ) {
@@ -273,12 +293,23 @@ class_names: ['file']
'\\',
$trimmed_arg
);
+
+ if( $format ) {
+ $namespace_formatted
+ = $formatter->formatClassNameOrNamespace(
+ $namespace
+ );
+ }
+
$argument = ( $convert_links )
? $formatter->namespaceToIdeHtmlLink(
$namespace,
- class_names: ['file']
+ class_names: ['file'],
+ text: $namespace_formatted
)
- : $namespace;
+ : ( ( $format )
+ ? $namespace_formatted
+ : $namespace );
$allow_html_entities = false;
}
diff --git a/dist/stonetable/lib/php-code-test-suite/OutputText/OutputTextFormatter.php b/dist/stonetable/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
index 4ac2819..2432b21 100644
--- a/dist/stonetable/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
+++ b/dist/stonetable/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -18,6 +18,8 @@
namespace PCTS\OutputText;
+use PCTS\PhpTokens\EnhancedPhpToken;
+
class OutputTextFormatter {
/** Files with the following file formats will be shortened. */
@@ -123,11 +125,52 @@ public function formatPathname(
return ($pathname . $text_suffix);
}
- $text = ($this->shortenPathname($pathname) . $text_suffix);
+ return $this->formatPathnameWithText(
+ $pathname,
+ $this->shortenPathname($pathname),
+ $text_suffix,
+ $line_number,
+ $column_number,
+ $class_names
+ );
+ }
+
+ /**
+ * Formats qualified/verified pathname.
+ *
+ * @param string $pathname Path name reference.
+ * @param string $text Text representation of the pathname.
+ * @param string $suffix Text suffix to add after formatted text.
+ * @param int|null $line_number Line number.
+ * @param int|null $column_number Column number.
+ * @param array|null $class_names When links are used, add these classes.
+ * @return string If HTML formatting is enabled, HTML formatted text,
+ * otherwise just plain text
+ */
+ protected function formatPathnameWithText(
+ string $pathname,
+ string $text,
+ string $suffix = '',
+ ?int $line_number = null,
+ ?int $column_number = null,
+ ?array $class_names = null
+ ): string {
+
+ $file_exists = file_exists($pathname);
+
+ if( $this->format_html ) {
+ $path_classes = [];
+ if( !$file_exists ) {
+ $path_classes[] = 'no-file';
+ }
+ $text = self::formatPathnameAddWrappers($text, $path_classes);
+ }
+
+ $text = ($text . $suffix);
$is_link = (
$this->format_html
+ && $file_exists
&& $this->convert_links
- && file_exists($pathname)
);
return ( $is_link )
@@ -141,6 +184,36 @@ public function formatPathname(
: $text;
}
+ /** Adds outer and inner HTML wrappers to the given pathname. */
+ public static function formatPathnameAddWrappers(
+ string $pathname,
+ array $path_classes = [],
+ array $base_classes = []
+ ): string {
+
+ $basename = basename($pathname);
+ $basename_len = strlen($basename);
+ $extension = pathinfo($pathname, PATHINFO_EXTENSION);
+ $path_classes = ['path', ...$path_classes];
+ $base_classes = ['base', ...$base_classes];
+
+ if( $extension === 'php' ) {
+ $base_classes[] = 'ext-php';
+ }
+
+ return sprintf(
+ '',
+ implode(' ', $path_classes)
+ )
+ . substr($pathname, 0, -$basename_len)
+ . sprintf(
+ '%s ',
+ implode(' ', $base_classes),
+ substr($pathname, -$basename_len)
+ )
+ . ' ';
+ }
+
/** Tells if the given value is recognized as a qualified namespace. */
public function isQualifiedNamespace(
string $value
@@ -163,10 +236,7 @@ public function format(
): string {
$result = $this->shortenFilenamesAll($text);
-
- if( $this->convert_links ) {
- $result = $this->convertNamespacesToHtmlLinks($result);
- }
+ $result = $this->formatNamespaces($result);
return $result;
}
@@ -190,8 +260,8 @@ public function shortenFilenamesAll(
return $text;
}
- /** Converts all namespaces to HTML hyperlinks in the given text string. */
- public function convertNamespacesToHtmlLinks(
+ /** Formats all namespaces to HTML. */
+ public function formatNamespaces(
string $text,
?\Closure $match_handler = null
): string {
@@ -205,9 +275,10 @@ public function convertNamespacesToHtmlLinks(
array_keys($this->vendor_data)
);
- // Mind the "preceeded by" character group.
$regex_str = sprintf(
- '#(\s|^|\?|\(|"|\')((%s)[A-Za-z0-9\\\\]+)#m',
+ // Mind the "preceeded by" character group.
+ // Curly brackets "{}" are used to include "{closure}"
+ '#(\s|^|\?|\(|"|\'|\||:|&)((%s)[A-Za-z0-9_{}\\\\]+)#m',
implode('|', $vendor_names)
);
@@ -219,23 +290,62 @@ public function convertNamespacesToHtmlLinks(
foreach( $matches[2] as $index => $match ) {
- [$namespace, $line_number] = $match;
- $vendor_name = rtrim($matches[3][$index][0], '\\');
+ [$ns_name, $line_number] = $match;
+ [$vendor_name, $ns_start_pos] = $matches[3][$index];
+ $vendor_name = rtrim($vendor_name, '\\');
+ $ns_name_len = strlen($ns_name);
if( !$match_handler ) {
- $wrapper = $this->namespaceToIdeHtmlLink($namespace);
+ $ns_end_pos = ($ns_start_pos + $ns_name_len + $offset);
+ $is_func = (
+ isset($text[$ns_end_pos])
+ && $text[$ns_end_pos] === '('
+ );
+ $is_closure = (
+ !$is_func
+ && EnhancedPhpToken::namespaceToParts($ns_name)['base']
+ === '{closure}'
+ );
+ $ns_name_classes = ( !$is_func )
+ ? []
+ : ['func'];
+ if( !$is_func && !$is_closure ) {
+ $filename = $this->namespaceToFilename($ns_name);
+ if( !$filename || !file_exists($filename) ) {
+ $ns_name_classes[] = 'no-file';
+ $wrapper = $ns_name;
+ } elseif( $this->convert_links ) {
+ $wrapper = self::buildIdeHtmlLink(
+ $filename,
+ $ns_name
+ );
+ } else {
+ $wrapper = $ns_name;
+ }
+ } else {
+ $wrapper = $ns_name;
+ }
+ $wrapper = $this->formatClassNameOrNamespace(
+ $wrapper,
+ $ns_name_classes
+ );
+ if( $is_func || $is_closure ) {
+ $wrapper .= '( '
+ . ') ';
+ $ns_name_len += 2;
+ }
} else {
- $wrapper = $match_handler($namespace, $vendor_name);
+ $wrapper = $match_handler($ns_name, $vendor_name);
}
$text = substr_replace(
$text,
$wrapper,
- ((int)$match[1] + $offset),
- strlen($match[0])
+ ((int)$line_number + $offset),
+ $ns_name_len
);
- $offset += (strlen($wrapper) - strlen($match[0]));
+ $offset += (strlen($wrapper) - $ns_name_len);
}
}
@@ -258,8 +368,8 @@ public function shortenFilenamesByPath(
// Not preceeded by "file/".
'#(?editable_file_formats)
);
@@ -281,41 +391,47 @@ public function shortenFilenamesByPath(
. $relative_path
);
$filename_length = strlen($filename);
-
- $is_link = (
- $this->format_html
- && $this->convert_links
- && file_exists($filename)
+ $is_on_line = (
+ isset($matches[6][$index])
+ && !empty($matches[6][$index][0])
+ && $matches[6][$index][1] !== -1
+ );
+ $is_column_num = (
+ isset($matches[8][$index])
+ && !empty($matches[8][$index][0])
+ && $matches[8][$index][1] !== -1
+ );
+ $replace_text = $this->formatPathnameWithText(
+ $filename,
+ $text_relative_path,
+ line_number: match(true) {
+ $is_on_line => (int)$matches[6][$index][0],
+ $is_column_num => (int)$matches[8][$index][0],
+ default => null
+ },
+ class_names: ['file']
);
-
- $replace_text = ( $is_link )
- ? self::buildIdeHtmlLink(
- $filename,
- $text_relative_path,
- ( (int)$matches[6][$index][0] ?: null ),
- class_names: ['file']
- )
- : $text_relative_path;
-
$text = substr_replace(
$text,
$replace_text,
((int)$match[1] + $offset),
$filename_length
);
-
$offset_add = (strlen($replace_text) - $filename_length);
$offset += $offset_add;
// Captured line number.
if(
$this->format_html
- && isset($matches[6][$index])
- && !empty($matches[6][$index][0])
- && $matches[6][$index][1] !== -1
+ && ($is_on_line || $is_column_num)
) {
- [$line_number, $line_number_pos] = $matches[6][$index];
+ if( $is_on_line ) {
+ [$line_number, $line_number_pos] = $matches[6][$index];
+ } else {
+ [$line_number, $line_number_pos] = $matches[8][$index];
+ }
+
$line_number_length = strlen($line_number);
$replace_text = sprintf(
'%s ',
@@ -338,16 +454,21 @@ class_names: ['file']
/** Converts a namespace to IDE open file HTML hyperlink. */
public function namespaceToIdeHtmlLink(
string $namespace,
- ?array $class_names = null
+ ?array $class_names = null,
+ ?string $text = null,
): ?string {
if( !$filename = $this->namespaceToFilename($namespace) ) {
return null;
}
+ if( !file_exists($filename) ) {
+ return null;
+ }
+
return self::buildIdeHtmlLink(
$filename,
- $namespace,
+ ( $text ?: $namespace ),
class_names: $class_names
);
}
@@ -416,10 +537,7 @@ public function buildIdeHtmlLink(
) )
);
- $html_link .= ( $text )
- ? $text
- : $filename;
-
+ $html_link .= ( $text ?: $filename );
$html_link .= '';
return $html_link;
@@ -558,7 +676,6 @@ public static function parseIdeUriFormat(
'line' => $line_number,
'column' => $column_number,
];
-
$result = $mem = '';
$format_len = strlen($ide_uri_format);
$curly_stack = [];
@@ -683,4 +800,95 @@ public static function parseIdeUriFormat(
return $result;
}
+
+ /** HTML formats given class name - either fully qualified or keyword. */
+ public function formatClassNameOrNamespace(
+ string $string,
+ array $ns_name_classes = []
+ ): string {
+
+ $separator_pos = strrpos($string, '\\');
+
+ // Namespace
+ if( $separator_pos !== false ) {
+ return $this->formatNamespaceName($string, $ns_name_classes);
+ // Class name
+ } else {
+ return sprintf(
+ '%s ',
+ $string
+ );
+ }
+ }
+
+ /**
+ * HTML formats namespace name
+ *
+ * @param string $ns_name Namespace name.
+ * @param array $ns_name_classes Classes to add to namespace name wrapper.
+ * @return string HTML formatted namespace name.
+ */
+ public function formatNamespaceName(
+ string $ns_name,
+ array $ns_name_classes = []
+ ): string {
+
+ $separator_pos = strrpos($ns_name, '\\');
+
+ if( $separator_pos === false ) {
+ throw new \Exception(
+ "Namespace name must contain backward slash separator"
+ );
+ }
+
+ $base = substr($ns_name, ($separator_pos + 1));
+
+ if( $base === '{closure}' ) {
+ $base = self::getFormattedClosureString();
+ $ns_name_classes[] = 'closure';
+ }
+
+ $ns_name_classes = ['ns-name', ...$ns_name_classes];
+
+ return
+ sprintf(
+ '',
+ implode(' ', $ns_name_classes)
+ )
+ . substr($ns_name, 0, ($separator_pos + 1))
+ . sprintf(
+ '%s ',
+ $base
+ )
+ . ' ';
+ }
+
+ /** Returns HTML formatted debug string for closure. */
+ public static function getFormattedClosureString(): string {
+
+ return '{ '
+ . 'closure'
+ . '} ';
+ }
+
+ /** HTML formats a simplified function name string. */
+ public function formatSimplifiedFunctionStr( string $func_str ): string {
+
+ if( str_ends_with($func_str, '()') ) {
+ $func_str = substr($func_str, -2);
+ }
+
+ $func_format = '%s ';
+ $punc_html = '( '
+ . ') ';
+
+ if( $func_str === '{closure}' ) {
+ $func_str = self::getFormattedClosureString();
+ }
+
+ return (sprintf(
+ $func_format,
+ $func_str
+ ) . $punc_html);
+ }
}
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
index 3c2a911..f33bd2e 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
index 776009e..25aee47 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php b/dist/stonetable/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
index 6067b5f..2053265 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -247,7 +247,7 @@ public function richFormatErrorMessage(
)
);
$result .= '';
- $result .= 'Location ';
+ $result .= 'Location ';
$line_number_suffix = sprintf(
':%d ',
$line_number
@@ -264,7 +264,7 @@ class_names: ['file']
if( $error_type !== null ) {
- $result .= 'Type ';
+ $result .= 'Type ';
$result .= sprintf(
'%s ',
self::errorTypeToString($error_type)
@@ -324,24 +324,27 @@ public function richFormatException(
close_html_tags: false
);
- $exception_namespace = $exception::class;
-
- $result .= 'Error Class ';
+ $result .= 'Error Class ';
$result .= '';
+ $exception_class = $exception::class;
+ $class_formatted = $this->formatter->formatClassNameOrNamespace(
+ $exception_class
+ );
- if( $this->formatter->isQualifiedNamespace($exception_namespace) ) {
+ if( $this->formatter->isQualifiedNamespace($exception_class) ) {
$result .= $this->formatter->namespaceToIdeHtmlLink(
- $exception_namespace
+ $exception_class,
+ text: $class_formatted
);
} else {
- $result .= $exception_namespace;
+ $result .= $class_formatted;
}
$result .= ' ';
- $result .= 'Error Code ';
+ $result .= 'Error Code ';
$result .= '';
$result .= $exception->getCode();
$result .= ' ';
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/BracketsEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
index bc17dee..daee8b2 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
index 9f6c55a..aaed0ff 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -45,6 +45,7 @@ class EnhancedPhpToken {
'noreturn',
'parent',
'self',
+ 'iterable',
'__COMPILER_HALT_OFFSET__',
];
@@ -95,8 +96,8 @@ public function isLeveled(): bool {
* @return bool True when found, and false when not found.
*/
public function lookAhead(
- array|string $while,
- array|string $until
+ int|array|string $while,
+ int|array|string $until
): bool {
$key = ($this->cache_key + 1);
@@ -171,25 +172,34 @@ public function isClassNameLookBehind(): bool {
}
$non_whitespace_tokens = [
- T_CLASS,
T_NEW,
T_INSTANCEOF,
T_EXTENDS,
T_INTERFACE,
+ T_IMPLEMENTS,
T_TRAIT,
T_ENUM,
// Traits
T_USE,
T_INSTEADOF,
- T_IMPLEMENTS,
];
- return $this->lookBehind([
+ $main_look_behind = $this->lookBehind([
+ T_WHITESPACE,
+ T_STRING,
+ T_CLASS,
+ ...$non_whitespace_tokens
+ ], [T_CLASS, ...$non_whitespace_tokens]);
+
+ #review: what role does comma exactly play?
+ $with_comma_look_behind = $this->lookBehind([
T_WHITESPACE,
',',
T_STRING,
...$non_whitespace_tokens
], $non_whitespace_tokens);
+
+ return $main_look_behind || $with_comma_look_behind;
}
/**
@@ -211,9 +221,11 @@ public function isNakedLookBehind( int $token_id ): bool {
/**
* Tells if current token might be a class name in catch clause.
*/
- public function isClassNameLookBehindForCatch(): bool {
+ public function isClassNameLookBehindForCatch(
+ int|string|array $is = T_STRING
+ ): bool {
- return ( !$this->token->is(T_STRING) )
+ return ( !$this->token->is($is) )
? false
: $this->lookBehind([
T_WHITESPACE,
@@ -252,6 +264,10 @@ public function isClassNameLookAhead(): bool {
return $this->lookAhead(
[T_WHITESPACE, T_VARIABLE, '|'],
[T_VARIABLE, '|'],
+ // Not preceeded by double colons.
+ ) && !$this->lookBehind(
+ [T_WHITESPACE, T_DOUBLE_COLON, T_PAAMAYIM_NEKUDOTAYIM],
+ [T_DOUBLE_COLON, T_PAAMAYIM_NEKUDOTAYIM]
);
}
@@ -687,10 +703,13 @@ public function getInnerHtml(): string {
*/
public function getNamespaceLastComponentType(): ?NUDTE {
- $type = NUDTE::CLASS_LIKE;
+ $type = NUDTE::CONSTANT;
+ $identified = false;
if( $context = $this->stream->getContext() ) {
+ $identified = true;
+
if( $context instanceof NamespaceUseDeclarationBuilder ) {
/* If there is a block statement in front, do not mark the last
@@ -706,6 +725,43 @@ public function getNamespaceLastComponentType(): ?NUDTE {
// Namespace definition will be presented as generic string.
$type = null;
+
+ } else {
+
+ $identified = false;
+ }
+
+ } elseif(
+ /* `isFunctionLookAhead` will not work here, because it can be a
+ "name" class token. */
+ $this->lookAhead([T_WHITESPACE, '('], '(')
+ && !$this->lookBehind([T_WHITESPACE, T_NEW], T_NEW)
+ ) {
+
+ $type = NUDTE::FUNCTION;
+ $identified = true;
+ }
+
+ if( !$identified ) {
+
+ $ns_name_parts = self::namespaceToParts($this->token->text);
+
+ if(
+ ($ns_name_parts['vendor'] && !$ns_name_parts['base'])
+ || (!$ns_name_parts['vendor'] && $ns_name_parts['base'])
+ || $this->lookAhead(
+ [T_WHITESPACE, T_DOUBLE_COLON],
+ T_DOUBLE_COLON
+ )
+ || $this->lookBehind([T_WHITESPACE, T_NEW], T_NEW)
+ || $this->lookBehind([T_WHITESPACE, T_USE], T_USE)
+ || $this->isClassNameLookBehindForCatch([
+ T_NAMESPACE,
+ T_NAME_QUALIFIED,
+ T_NAME_FULLY_QUALIFIED
+ ])
+ ) {
+ $type = NUDTE::CLASS_LIKE;
}
}
@@ -838,4 +894,38 @@ public static function getNamespaceInnerHtml(
return $result;
}
+
+ /** Returns parts for a given namespace name. */
+ public static function namespaceToParts( string $ns_name ): array {
+
+ $divider_pos = strpos($ns_name, '\\');
+
+ if( $divider_pos !== false ) {
+
+ $divider_pos_last = strrpos($ns_name, '\\');
+
+ return [
+ 'vendor' => substr($ns_name, 0, $divider_pos),
+ 'parts' => ($divider_pos !== $divider_pos_last)
+ ? explode(
+ '\\',
+ substr(
+ $ns_name,
+ ($divider_pos + 1),
+ $divider_pos_last - ($divider_pos + 1)
+ )
+ )
+ : [],
+ 'base' => substr($ns_name, ($divider_pos_last + 1)),
+ ];
+
+ } else {
+
+ return [
+ 'vendor' => $ns_name,
+ 'parts' => [],
+ 'base' => '',
+ ];
+ }
+ }
}
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
index cb1a3eb..8f551b3 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
index 7f69f11..2bd7f1e 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
index e9f4744..ab761c7 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
index 0289e7f..22c7a46 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
index fed90ea..c2bdb0f 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
index 392ab45..cfb50f8 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
index 1ce5d67..72304da 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
index aef187f..d979999 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
index 303bdfb..9194c22 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
@@ -11,7 +11,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
index 24de334..606aad9 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
index ace2630..dff3d66 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
index 6a74081..e548f1a 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
index aaed27c..6f36c7b 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
index d948a05..b733146 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
index 71e5aee..bb9f664 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
index 2dc7951..206ab94 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
index e472619..de985b0 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
index 1651099..1015ef8 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
index af21e05..9da4daf 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/PlacementEnum.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
index 4c52fac..f21074d 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Tokenizer.php b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Tokenizer.php
index bbaa995..b02a91b 100644
--- a/dist/stonetable/lib/php-code-test-suite/PhpTokens/Tokenizer.php
+++ b/dist/stonetable/lib/php-code-test-suite/PhpTokens/Tokenizer.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/utilities/AbstractHandler.php b/dist/stonetable/lib/php-code-test-suite/utilities/AbstractHandler.php
index 3ff47db..620fb7b 100644
--- a/dist/stonetable/lib/php-code-test-suite/utilities/AbstractHandler.php
+++ b/dist/stonetable/lib/php-code-test-suite/utilities/AbstractHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/utilities/ClosureHandler.php b/dist/stonetable/lib/php-code-test-suite/utilities/ClosureHandler.php
index b168f56..7a6b3a8 100644
--- a/dist/stonetable/lib/php-code-test-suite/utilities/ClosureHandler.php
+++ b/dist/stonetable/lib/php-code-test-suite/utilities/ClosureHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/utilities/IncludeHandler.php b/dist/stonetable/lib/php-code-test-suite/utilities/IncludeHandler.php
index 7685b0c..5011680 100644
--- a/dist/stonetable/lib/php-code-test-suite/utilities/IncludeHandler.php
+++ b/dist/stonetable/lib/php-code-test-suite/utilities/IncludeHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/php-code-test-suite/utilities/utilities.php b/dist/stonetable/lib/php-code-test-suite/utilities/utilities.php
index d3c042f..b1215f5 100644
--- a/dist/stonetable/lib/php-code-test-suite/utilities/utilities.php
+++ b/dist/stonetable/lib/php-code-test-suite/utilities/utilities.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/Autoload.php b/dist/stonetable/lib/project-directory/Autoload.php
index 29c12bb..45d6b81 100644
--- a/dist/stonetable/lib/project-directory/Autoload.php
+++ b/dist/stonetable/lib/project-directory/Autoload.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/BranchedTestDirectory.php b/dist/stonetable/lib/project-directory/BranchedTestDirectory.php
index ff13508..97f17de 100644
--- a/dist/stonetable/lib/project-directory/BranchedTestDirectory.php
+++ b/dist/stonetable/lib/project-directory/BranchedTestDirectory.php
@@ -12,7 +12,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/DemoSpecialComment.php b/dist/stonetable/lib/project-directory/DemoSpecialComment.php
index 20d8a41..7309644 100644
--- a/dist/stonetable/lib/project-directory/DemoSpecialComment.php
+++ b/dist/stonetable/lib/project-directory/DemoSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/FileIterator.php b/dist/stonetable/lib/project-directory/FileIterator.php
index 97cec01..069708e 100644
--- a/dist/stonetable/lib/project-directory/FileIterator.php
+++ b/dist/stonetable/lib/project-directory/FileIterator.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/FileTrait.php b/dist/stonetable/lib/project-directory/FileTrait.php
index a91cda4..e93f3c6 100644
--- a/dist/stonetable/lib/project-directory/FileTrait.php
+++ b/dist/stonetable/lib/project-directory/FileTrait.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/LinkSpecialComment.php b/dist/stonetable/lib/project-directory/LinkSpecialComment.php
index 330586e..192a3ca 100644
--- a/dist/stonetable/lib/project-directory/LinkSpecialComment.php
+++ b/dist/stonetable/lib/project-directory/LinkSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/MainDirectoriesEnum.php b/dist/stonetable/lib/project-directory/MainDirectoriesEnum.php
index 615e0c8..f58f558 100644
--- a/dist/stonetable/lib/project-directory/MainDirectoriesEnum.php
+++ b/dist/stonetable/lib/project-directory/MainDirectoriesEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/PlaygroundFile.php b/dist/stonetable/lib/project-directory/PlaygroundFile.php
index 28b846a..bbcb2ed 100644
--- a/dist/stonetable/lib/project-directory/PlaygroundFile.php
+++ b/dist/stonetable/lib/project-directory/PlaygroundFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/ProjectDirectory.php b/dist/stonetable/lib/project-directory/ProjectDirectory.php
index a0b0bc2..638bb7c 100644
--- a/dist/stonetable/lib/project-directory/ProjectDirectory.php
+++ b/dist/stonetable/lib/project-directory/ProjectDirectory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/ProjectFile.php b/dist/stonetable/lib/project-directory/ProjectFile.php
index a0d3478..67425a8 100644
--- a/dist/stonetable/lib/project-directory/ProjectFile.php
+++ b/dist/stonetable/lib/project-directory/ProjectFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -188,7 +188,6 @@ public function replaceByCoords(
}
$data = ($before_portion . $replacement);
-
$file_size = $this->file->getSize();
if( $coords[1] < $file_size ) {
@@ -400,6 +399,39 @@ public function rebuildSpecialComment(
}
}
+ /** Removes given special comment. */
+ public function removeSpecialComment(
+ SpecialComment $special_comment
+ ): ?bool {
+
+ if( $this->file->getSize() && $this->isSupportedFileType() ) {
+
+ $coords = $this->containsSpecialComment($special_comment);
+
+ if( !$coords ) {
+ return null;
+ }
+
+ $this->file->rewind();
+ clearstatcache();
+
+ while(
+ $this->file->fseek($coords[1]) === 0
+ && ($char = $this->file->fread(1)) !== false
+ && ( $char === "\r" || $char === "\n" )
+ ) {
+ $coords[1]++;
+ }
+
+ return $this->replaceByCoords($coords, '');
+
+ // File is empty or unsupported.
+ } else {
+
+ return null;
+ }
+ }
+
/** Rebuilds all special comments. */
public function rebuildAllSpecialCommentLines(): ?bool {
@@ -422,6 +454,28 @@ public function rebuildAllSpecialCommentLines(): ?bool {
}
}
+ /** Removes all special comments. */
+ public function removeAllSpecialCommentLines(): ?bool {
+
+ if( $this->file->getSize() && $this->isSupportedFileType() ) {
+
+ foreach( $this->special_comments as $special_comment ):
+
+ if( $this->removeSpecialComment($special_comment) === false ) {
+ return false;
+ }
+
+ endforeach;
+
+ return true;
+
+ // File is empty or unsupported.
+ } else {
+
+ return null;
+ }
+ }
+
/** Retrieves full contents of this file. */
public function getContents(): string|false {
diff --git a/dist/stonetable/lib/project-directory/ProjectFileObject.php b/dist/stonetable/lib/project-directory/ProjectFileObject.php
index d7e0beb..c2d3e75 100644
--- a/dist/stonetable/lib/project-directory/ProjectFileObject.php
+++ b/dist/stonetable/lib/project-directory/ProjectFileObject.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/ProjectFileObjectFactory.php b/dist/stonetable/lib/project-directory/ProjectFileObjectFactory.php
index fdc7e1b..4a055b7 100644
--- a/dist/stonetable/lib/project-directory/ProjectFileObjectFactory.php
+++ b/dist/stonetable/lib/project-directory/ProjectFileObjectFactory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/ProjectRootDirectory.php b/dist/stonetable/lib/project-directory/ProjectRootDirectory.php
index 432cc19..9233f25 100644
--- a/dist/stonetable/lib/project-directory/ProjectRootDirectory.php
+++ b/dist/stonetable/lib/project-directory/ProjectRootDirectory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/RecursiveFileIterator.php b/dist/stonetable/lib/project-directory/RecursiveFileIterator.php
index 4f9336e..f347cee 100644
--- a/dist/stonetable/lib/project-directory/RecursiveFileIterator.php
+++ b/dist/stonetable/lib/project-directory/RecursiveFileIterator.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/SourceFile.php b/dist/stonetable/lib/project-directory/SourceFile.php
index 6926e21..8c80326 100644
--- a/dist/stonetable/lib/project-directory/SourceFile.php
+++ b/dist/stonetable/lib/project-directory/SourceFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/SourceSpecialComment.php b/dist/stonetable/lib/project-directory/SourceSpecialComment.php
index 71b48f4..7a10c56 100644
--- a/dist/stonetable/lib/project-directory/SourceSpecialComment.php
+++ b/dist/stonetable/lib/project-directory/SourceSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/SpecialComment.php b/dist/stonetable/lib/project-directory/SpecialComment.php
index 5e02ef6..0524d32 100644
--- a/dist/stonetable/lib/project-directory/SpecialComment.php
+++ b/dist/stonetable/lib/project-directory/SpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/StaticFile.php b/dist/stonetable/lib/project-directory/StaticFile.php
index e8b93ab..93590cb 100644
--- a/dist/stonetable/lib/project-directory/StaticFile.php
+++ b/dist/stonetable/lib/project-directory/StaticFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/stonetable/lib/project-directory/StaticSpecialComment.php b/dist/stonetable/lib/project-directory/StaticSpecialComment.php
index 58f6912..b125db4 100644
--- a/dist/stonetable/lib/project-directory/StaticSpecialComment.php
+++ b/dist/stonetable/lib/project-directory/StaticSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.4
*/
diff --git a/dist/stonetable/lib/project-directory/TestFile.php b/dist/stonetable/lib/project-directory/TestFile.php
index 8147aaf..2fcbbf4 100644
--- a/dist/stonetable/lib/project-directory/TestFile.php
+++ b/dist/stonetable/lib/project-directory/TestFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/dist/web/stonetable/api/directory-listing.php b/dist/web/stonetable/api/directory-listing.php
index d901187..e30e81d 100644
--- a/dist/web/stonetable/api/directory-listing.php
+++ b/dist/web/stonetable/api/directory-listing.php
@@ -47,7 +47,6 @@
}
$charset = 'UTF-8';
-$transliterator = 'Any-Latin; Latin-ASCII';
$has_search_query = ( $search_query !== null );
if( !$has_search_query ) {
@@ -58,12 +57,17 @@
} else {
$file_iterator = $project_file_object->getRecursiveIterator();
-
+ $has_transliterator = function_exists('transliterator_transliterate');
+ $transliterator = 'Any-Latin; Latin-ASCII';
$comparable_search_query = mb_strtolower($search_query, $charset);
- $comparable_search_query = transliterator_transliterate(
- $transliterator,
- $comparable_search_query
- );
+
+ if( $has_transliterator ) {
+
+ $comparable_search_query = transliterator_transliterate(
+ $transliterator,
+ $comparable_search_query
+ );
+ }
}
$data = [];
@@ -91,10 +95,13 @@
$charset
);
- $comparable_searchable_str = transliterator_transliterate(
- $transliterator,
- $comparable_searchable_str
- );
+ if( $has_transliterator ) {
+
+ $comparable_searchable_str = transliterator_transliterate(
+ $transliterator,
+ $comparable_searchable_str
+ );
+ }
if(
mb_strpos(
diff --git a/dist/web/stonetable/api/file-handler.php b/dist/web/stonetable/api/file-handler.php
index b4dd1ae..529caa0 100644
--- a/dist/web/stonetable/api/file-handler.php
+++ b/dist/web/stonetable/api/file-handler.php
@@ -38,6 +38,9 @@
);
}
+$force_source = get_value_exists('force_source', '0');
+$force_source = ( is_numeric($force_source) && $force_source === '1' );
+
/**
* Enumerates view handler names.
*/
@@ -46,7 +49,7 @@ enum ViewHandlersEnum: string {
case OUTPUT_CODE_PARTS = 'demo-output';
}
-$handler_name = ( $project_file_object instanceof TestFile )
+$handler_name = ( ($project_file_object instanceof TestFile) && !$force_source )
? ViewHandlersEnum::OUTPUT_CODE_PARTS
: ViewHandlersEnum::SOURCE_CODE_PARTS;
@@ -225,7 +228,7 @@ function( string $value ) use( &$i ): string {
$inner_html,
$known_vendors_by_base
);
- $inner_html = $formatter->convertNamespacesToHtmlLinks(
+ $inner_html = $formatter->formatNamespaces(
$inner_html,
function(
string $namespace,
diff --git a/dist/web/stonetable/api/projects-listing.php b/dist/web/stonetable/api/projects-listing.php
index eb401cd..d3d5ec4 100644
--- a/dist/web/stonetable/api/projects-listing.php
+++ b/dist/web/stonetable/api/projects-listing.php
@@ -55,16 +55,17 @@
$search_query = get_value_exists('project_search_query');
$has_search_query = ( $search_query !== null );
-$search_query_limit = 100;
$charset = 'UTF-8';
$transliterator = 'Any-Latin; Latin-ASCII';
if( $has_search_query ) {
- $search_query = transliterator_transliterate(
- $transliterator,
- mb_strtolower($search_query, $charset)
- );
+ $search_query_limit = 100;
+ $has_transliterator = function_exists('transliterator_transliterate');
+ $search_query_lc = mb_strtolower($search_query, $charset);
+ $search_query = ( $has_transliterator )
+ ? transliterator_transliterate($transliterator, $search_query_lc)
+ : $search_query_lc;
if( mb_strlen($search_query) > $search_query_limit ) {
send_error(
@@ -77,6 +78,10 @@
$index = 0;
$select_from = (($page_number - 1) * $entries_per_page + 1);
$select_to = ($select_from + $entries_per_page - 1);
+$config_file_ending = (DIRECTORY_SEPARATOR
+ . ProjectRootDirectory::SYS_CONFIG_DIR_NAME
+ . DIRECTORY_SEPARATOR
+ . ProjectRootDirectory::SYS_CONFIG_FILE_NAME);
foreach( $file_iterator as $fileinfo ) {
@@ -85,20 +90,16 @@
if(
$fileinfo->isDir()
&& !str_starts_with($file_name, '.')
- && file_exists(
- $fileinfo->getPathname()
- . DIRECTORY_SEPARATOR
- . ProjectRootDirectory::SYS_CONFIG_DIR_NAME
- . DIRECTORY_SEPARATOR
- . ProjectRootDirectory::SYS_CONFIG_FILE_NAME
- )
+ && file_exists($fileinfo->getPathname() . $config_file_ending)
&& (
!$has_search_query
|| mb_strpos(
- transliterator_transliterate(
- $transliterator,
- mb_strtolower($file_name, $charset)
- ),
+ ( ( $has_transliterator )
+ ? transliterator_transliterate(
+ $transliterator,
+ mb_strtolower($file_name, $charset)
+ )
+ : mb_strtolower($file_name, $charset) ),
$search_query,
encoding: $charset
) !== false
@@ -143,7 +144,7 @@
$data[] = [
'title' => $title,
'pathname' => '/foo/bar',
- 'url' => 'https://localhost/',
+ 'url' => 'http://localhost/',
];
}
}
diff --git a/dist/web/stonetable/api/rebuild-special-comments.php b/dist/web/stonetable/api/rebuild-special-comments.php
index df7d209..64af835 100644
--- a/dist/web/stonetable/api/rebuild-special-comments.php
+++ b/dist/web/stonetable/api/rebuild-special-comments.php
@@ -26,7 +26,6 @@
!($project_file_object instanceof SourceFile)
&& !($project_file_object instanceof TestFile)
) {
-
send_error(
"File $path does not represent a source, or a test file"
);
diff --git a/dist/web/stonetable/api/remove-special-comments.php b/dist/web/stonetable/api/remove-special-comments.php
new file mode 100644
index 0000000..6fabd46
--- /dev/null
+++ b/dist/web/stonetable/api/remove-special-comments.php
@@ -0,0 +1,42 @@
+find($path);
+
+if( !$project_file_object ) {
+ send_error("File with path $path was not found");
+}
+
+if(
+ !($project_file_object instanceof SourceFile)
+ && !($project_file_object instanceof TestFile)
+) {
+ send_error(
+ "File $path does not represent a source, or a test file"
+ );
+}
+
+$remove_result = $project_file_object->removeAllSpecialCommentLines();
+
+if( $remove_result === false ) {
+ send_error("Could not remove special comment lines");
+} elseif( $remove_result === null ) {
+ send_error("There was nothing to remove");
+} else {
+ send_success([]);
+}
diff --git a/dist/web/stonetable/app/index.html b/dist/web/stonetable/app/index.html
index 233a889..44fd21d 100644
--- a/dist/web/stonetable/app/index.html
+++ b/dist/web/stonetable/app/index.html
@@ -1 +1 @@
-Stonetable Connect Please provide a working URL to the get-endpoints.php file, which is located in /api directory.
URL:
Continue
Load more No Projects Found
Stonetable v Checking latest version... You are running the latest version. A new v version is out. Please download the update . Error checking the latest version.
Stonetable is created by LWIS Technologies . This project is released under the MIT License .
© LWIS Technologies
\ No newline at end of file
+Stonetable Connect Please provide a working URL to the get-endpoints.php file, which is located in /api directory.
URL:
Continue
Load more No Projects Found
Stonetable v Checking latest version... You are running the latest version. A new v version is out. Please download the update . Error checking the latest version.
Stonetable is created by LWIS Technologies . This project is released under the MIT License .
© LWIS Technologies
\ No newline at end of file
diff --git a/dist/web/stonetable/assets/css/code-message.css b/dist/web/stonetable/assets/css/code-message.css
index d73b2e6..d5baeb7 100644
--- a/dist/web/stonetable/assets/css/code-message.css
+++ b/dist/web/stonetable/assets/css/code-message.css
@@ -1 +1 @@
-.code-msg{border:1px dashed #ccc;display:flex;flex-direction:column;gap:1em;margin:15px 0 0;padding:15px}.code-msg>*{margin:0}.code-msg :any-link{text-decoration:underline;text-decoration-color:#666;text-decoration-style:dotted;text-underline-offset:4px}.code-msg :any-link:hover{text-decoration-style:solid}.code-msg a,.code-msg code{overflow-wrap:anywhere}.code-msg code{font-family:Menlo,Monaco,Courier New,monospace;font-size:90%}.code-msg>.h{color:#666}.code-msg .arg-l{display:flex;flex-wrap:wrap;list-style-type:none;margin:0;padding:0}.code-msg .arg-l>li{counter-increment:argument-counter}.code-msg .arg-l>li:before{background-color:#eee;border-radius:5px;content:counter(argument-counter);display:inline-flex;font-size:80%;margin-right:3px;padding:1px 3px}.code-msg .arg-l>li:not(:last-child){margin-right:5px}.code-msg .arg-l>li:not(:last-child):after{content:","}.code-msg dl{column-gap:15px;display:grid;grid-template-columns:max-content 1fr;margin:0}.code-msg dl>dt{color:#666}.code-msg dl>dd{margin:0}.code-msg .stk-tr-l{list-style-type:decimal;padding-left:40px}.code-msg .stk-tr-l>li::marker{color:#666}.code-msg-err{border-color:#e42a2a}.code-msg-warn{border-color:#f48424}.code-msg-note{border-color:#ece130}.code-msg-dep{border-color:#516f79}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#001180)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#0a00ff)}.code-msg .func-name{color:var(--code-php-highlight-function,#795e27)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#0a8658)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#0531fa)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#0a8658)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#a21515)}@media (prefers-color-scheme:dark){.code-msg .arg-l>li:before{background-color:#111}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#9ddbfe)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#559cd6)}.code-msg .func-name{color:var(--code-php-highlight-function,#dcdcaa)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#ffd601)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#ce9278)}}
\ No newline at end of file
+:root{--pathname-base-highlight:#669321;--pathname-base-highlight-php:#9f74c4}@media (prefers-color-scheme:dark){:root{--pathname-base-highlight:#669321;--pathname-base-highlight-php:#9f74c4}}.code-msg{border:1px dashed #ccc;display:flex;flex-direction:column;gap:1em;margin:15px 0 0;padding:15px}.code-msg>*{margin:0}.code-msg :any-link{text-decoration:underline;text-decoration-color:#666;text-decoration-style:dotted;text-underline-offset:4px}.code-msg :any-link:hover{text-decoration-style:solid}.code-msg a,.code-msg code{overflow-wrap:anywhere}.code-msg code{font-family:Menlo,Monaco,Courier New,monospace;font-size:90%}.code-msg>.h{color:#666}.code-msg .arg-l{display:flex;flex-wrap:wrap;list-style-type:none;margin:0;padding:0}.code-msg .arg-l>li{counter-increment:argument-counter}.code-msg .arg-l>li:before{background-color:#eee;border-radius:5px;content:counter(argument-counter);display:inline-flex;font-size:80%;margin-right:3px;padding:1px 3px}.code-msg .arg-l>li:not(:last-child){margin-right:5px}.code-msg .arg-l>li:not(:last-child):after{content:","}.code-msg dl{column-gap:15px;display:grid;grid-template-columns:max-content 1fr;margin:0}.code-msg dl>dt{color:#666}.code-msg dl>dd{margin:0}.code-msg .err-code+dd{color:var(--code-php-highlight-number,#0a8658)}.code-msg .stk-tr-l{list-style-type:decimal;padding-left:40px}.code-msg .stk-tr-l>li::marker{color:#666}.code-msg-err{border-color:#e42a2a}.code-msg-warn{border-color:#f48424}.code-msg-note{border-color:#ece130}.code-msg-dep{border-color:#516f79}.code-msg .path .base{color:var(--pathname-base-highlight)}.code-msg .path .base.ext-php{color:var(--pathname-base-highlight-php)}.code-msg .ns-name.no-file,.code-msg .path.no-file{text-decoration:underline var(--bg-color-restrained,#666) wavy;-webkit-text-decoration:underline var(--bg-color-restrained,#666) wavy;text-decoration-thickness:1px;text-underline-offset:3px}.code-msg .cls-name,.code-msg .ns-name .base{color:var(--code-php-highlight-class-name,#257e99)}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#001180)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#0a00ff)}.code-msg .func-name,.code-msg .ns-name.closure .base,.code-msg .ns-name.func .base{color:var(--code-php-highlight-function,#795e27)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#0a8658)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#0531fa)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#0a8658)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#a21515)}@media (prefers-color-scheme:dark){.code-msg .arg-l>li:before{background-color:#111}.code-msg .err-code+dd{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .cls-name,.code-msg .ns-name .base{color:var(--code-php-highlight-class-name,#4ec9b0)}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#9ddbfe)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#559cd6)}.code-msg .func-name,.code-msg .ns-name.closure .base,.code-msg .ns-name.func .base{color:var(--code-php-highlight-function,#dcdcaa)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#ffd601)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#ce9278)}}
\ No newline at end of file
diff --git a/dist/web/stonetable/assets/css/output.css b/dist/web/stonetable/assets/css/output.css
index 37b3124..813c6ab 100644
--- a/dist/web/stonetable/assets/css/output.css
+++ b/dist/web/stonetable/assets/css/output.css
@@ -1 +1 @@
-.code-msg{border:1px dashed #ccc;display:flex;flex-direction:column;gap:1em;margin:15px 0 0;padding:15px}.code-msg>*{margin:0}.code-msg :any-link{text-decoration:underline;text-decoration-color:#666;text-decoration-style:dotted;text-underline-offset:4px}.code-msg :any-link:hover{text-decoration-style:solid}.code-msg a,.code-msg code{overflow-wrap:anywhere}.code-msg code{font-family:Menlo,Monaco,Courier New,monospace;font-size:90%}.code-msg>.h{color:#666}.code-msg .arg-l{display:flex;flex-wrap:wrap;list-style-type:none;margin:0;padding:0}.code-msg .arg-l>li{counter-increment:argument-counter}.code-msg .arg-l>li:before{background-color:#eee;border-radius:5px;content:counter(argument-counter);display:inline-flex;font-size:80%;margin-right:3px;padding:1px 3px}.code-msg .arg-l>li:not(:last-child){margin-right:5px}.code-msg .arg-l>li:not(:last-child):after{content:","}.code-msg dl{column-gap:15px;display:grid;grid-template-columns:max-content 1fr;margin:0}.code-msg dl>dt{color:#666}.code-msg dl>dd{margin:0}.code-msg .stk-tr-l{list-style-type:decimal;padding-left:40px}.code-msg .stk-tr-l>li::marker{color:#666}.code-msg-err{border-color:#e42a2a}.code-msg-warn{border-color:#f48424}.code-msg-note{border-color:#ece130}.code-msg-dep{border-color:#516f79}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#001180)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#0a00ff)}.code-msg .func-name{color:var(--code-php-highlight-function,#795e27)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#0a8658)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#0531fa)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#0a8658)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#a21515)}@media (prefers-color-scheme:dark){.code-msg .arg-l>li:before{background-color:#111}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#9ddbfe)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#559cd6)}.code-msg .func-name{color:var(--code-php-highlight-function,#dcdcaa)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#ffd601)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#ce9278)}}:root{--bg-color:#fff;--text-color:#1e1e1e;--divider-color:#bbb;color-scheme:light dark}*,:after,:before{box-sizing:border-box}body,html{margin:0;padding:0}html{font:16px/1.5 system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;height:100%}body{background-color:var(--bg-color);color:var(--text-color);min-height:100%;padding:52px 15px 15px}:any-link{color:inherit}.tb,.tb *{display:flex}.tb{background-color:var(--bg-color);border-bottom:1px solid var(--divider-color);color:var(--text-color);height:52px;left:0;overflow:auto hidden;padding:3px;position:fixed;right:0;scrollbar-width:thin;top:0}.tb nav{margin-left:auto}.tb nav :any-link{text-decoration:none}.tb nav ul{list-style:none;margin:0;padding:0}.tb nav li{white-space:nowrap}.tb nav a{align-items:center;border-radius:5px;height:45px;justify-content:center;padding:3px 12px;text-align:center}.tb nav a:hover{background-color:#eee}.o{border:1px dashed #666;font:13px/1.5 Menlo,Monaco,Courier New,monospace;margin:15px 0 0;padding:15px;white-space:pre-wrap}.o :any-link{text-decoration:underline;text-decoration-skip-ink:auto;text-decoration-skip-ink:all;text-decoration-style:dotted;text-underline-offset:3px}.o :any-link:hover{text-decoration-style:solid}@media (prefers-color-scheme:dark){:root{--bg-color:#1e1e1e;--text-color:#ccc;--divider-color:#111}.tb nav a:hover{background-color:#111}}
\ No newline at end of file
+:root{--pathname-base-highlight:#669321;--pathname-base-highlight-php:#9f74c4}@media (prefers-color-scheme:dark){:root{--pathname-base-highlight:#669321;--pathname-base-highlight-php:#9f74c4}}.code-msg{border:1px dashed #ccc;display:flex;flex-direction:column;gap:1em;margin:15px 0 0;padding:15px}.code-msg>*{margin:0}.code-msg :any-link{text-decoration:underline;text-decoration-color:#666;text-decoration-style:dotted;text-underline-offset:4px}.code-msg :any-link:hover{text-decoration-style:solid}.code-msg a,.code-msg code{overflow-wrap:anywhere}.code-msg code{font-family:Menlo,Monaco,Courier New,monospace;font-size:90%}.code-msg>.h{color:#666}.code-msg .arg-l{display:flex;flex-wrap:wrap;list-style-type:none;margin:0;padding:0}.code-msg .arg-l>li{counter-increment:argument-counter}.code-msg .arg-l>li:before{background-color:#eee;border-radius:5px;content:counter(argument-counter);display:inline-flex;font-size:80%;margin-right:3px;padding:1px 3px}.code-msg .arg-l>li:not(:last-child){margin-right:5px}.code-msg .arg-l>li:not(:last-child):after{content:","}.code-msg dl{column-gap:15px;display:grid;grid-template-columns:max-content 1fr;margin:0}.code-msg dl>dt{color:#666}.code-msg dl>dd{margin:0}.code-msg .err-code+dd{color:var(--code-php-highlight-number,#0a8658)}.code-msg .stk-tr-l{list-style-type:decimal;padding-left:40px}.code-msg .stk-tr-l>li::marker{color:#666}.code-msg-err{border-color:#e42a2a}.code-msg-warn{border-color:#f48424}.code-msg-note{border-color:#ece130}.code-msg-dep{border-color:#516f79}.code-msg .path .base{color:var(--pathname-base-highlight)}.code-msg .path .base.ext-php{color:var(--pathname-base-highlight-php)}.code-msg .ns-name.no-file,.code-msg .path.no-file{text-decoration:underline var(--bg-color-restrained,#666) wavy;-webkit-text-decoration:underline var(--bg-color-restrained,#666) wavy;text-decoration-thickness:1px;text-underline-offset:3px}.code-msg .cls-name,.code-msg .ns-name .base{color:var(--code-php-highlight-class-name,#257e99)}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#001180)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#0a00ff)}.code-msg .func-name,.code-msg .ns-name.closure .base,.code-msg .ns-name.func .base{color:var(--code-php-highlight-function,#795e27)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#0a8658)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#0531fa)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#0a8658)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#a21515)}@media (prefers-color-scheme:dark){.code-msg .arg-l>li:before{background-color:#111}.code-msg .err-code+dd{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .cls-name,.code-msg .ns-name .base{color:var(--code-php-highlight-class-name,#4ec9b0)}.code-msg .code-php .var{color:var(--code-php-highlight-variable,#9ddbfe)}.code-msg .code-php .type{color:var(--code-php-highlight-keyword,#559cd6)}.code-msg .func-name,.code-msg .ns-name.closure .base,.code-msg .ns-name.func .base{color:var(--code-php-highlight-function,#dcdcaa)}.code-msg .arg-l .float .text,.code-msg .arg-l .int .text,.code-msg .line-num{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .punc-brkt{color:var(--code-php-highlight-punctuation-level-1n,#ffd601)}.code-msg .arg-l .info{color:var(--code-php-highlight-number,#b6cda8)}.code-msg .arg-l .string .text{color:var(--code-php-highlight-string,#ce9278)}}:root{--bg-color:#fff;--text-color:#1e1e1e;--divider-color:#bbb;color-scheme:light dark}*,:after,:before{box-sizing:border-box}body,html{margin:0;padding:0}html{font:16px/1.5 system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;height:100%}body{background-color:var(--bg-color);color:var(--text-color);min-height:100%;padding:52px 15px 15px}:any-link{color:inherit}.tb,.tb *{display:flex}.tb{background-color:var(--bg-color);border-bottom:1px solid var(--divider-color);color:var(--text-color);height:52px;left:0;overflow:auto hidden;padding:3px;position:fixed;right:0;scrollbar-width:thin;top:0}.tb nav{margin-left:auto}.tb nav :any-link{text-decoration:none}.tb nav ul{list-style:none;margin:0;padding:0}.tb nav li{white-space:nowrap}.tb nav a{align-items:center;border-radius:5px;height:45px;justify-content:center;padding:3px 12px;text-align:center}.tb nav a:hover{background-color:#eee}.o{border:1px dashed #666;font:13px/1.5 Menlo,Monaco,Courier New,monospace;margin:15px 0 0;padding:15px;white-space:pre-wrap}.o :any-link{text-decoration:underline;text-decoration-skip-ink:auto;text-decoration-skip-ink:all;text-decoration-style:dotted;text-underline-offset:3px}.o :any-link:hover{text-decoration-style:solid}.o>.code-msg{font:16px/1.5 system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif}@media (prefers-color-scheme:dark){:root{--bg-color:#1e1e1e;--text-color:#ccc;--divider-color:#111}.tb nav a:hover{background-color:#111}}
\ No newline at end of file
diff --git a/dist/web/stonetable/config.php b/dist/web/stonetable/config.php
index a6da743..134fee9 100644
--- a/dist/web/stonetable/config.php
+++ b/dist/web/stonetable/config.php
@@ -3,7 +3,7 @@
declare(strict_types=1);
/**
- * Path name to the directory containing web projects.
+ * Path name to the directory containing PHP projects.
*
* Trailing slash should be excluded. Please normalize using `realpath()` if
* required.
diff --git a/dist/web/stonetable/demo-page-init.php b/dist/web/stonetable/demo-page-init.php
index d6eeee2..cafddb1 100644
--- a/dist/web/stonetable/demo-page-init.php
+++ b/dist/web/stonetable/demo-page-init.php
@@ -393,5 +393,3 @@ function assert_true( mixed $value, string $error_message ): void {
define(__NAMESPACE__ . '\ERROR_HANDLER', $dpi_error_handler);
define(__NAMESPACE__ . '\DEBUGGER', $dpi_debugger);
-
-namespace UserDemo;
diff --git a/src/lib/php-code-test-suite/Autoload.php b/src/lib/php-code-test-suite/Autoload.php
index 1d77ea6..ddcaeb3 100644
--- a/src/lib/php-code-test-suite/Autoload.php
+++ b/src/lib/php-code-test-suite/Autoload.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/Debugger/Debugger.php b/src/lib/php-code-test-suite/Debugger/Debugger.php
index b6bc11c..825ba5a 100644
--- a/src/lib/php-code-test-suite/Debugger/Debugger.php
+++ b/src/lib/php-code-test-suite/Debugger/Debugger.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -168,11 +168,11 @@ public function traceDataToCompactLine(
if( $format ) {
- $result .= sprintf(
- '%s ',
- ( $trace_data['class']
- ?? $formatter->shortenPathname($filename) )
- );
+ $result .= ( isset($trace_data['class']) )
+ ? $formatter->formatClassNameOrNamespace($trace_data['class'])
+ : $formatter::formatPathnameAddWrappers(
+ $formatter->shortenPathname($filename)
+ );
} else {
@@ -180,6 +180,7 @@ public function traceDataToCompactLine(
}
if( !isset($trace_data['class']) && $trace_data['line'] ) {
+
$result .= ( $format )
? sprintf(
':%d '
@@ -190,22 +191,34 @@ public function traceDataToCompactLine(
}
$result .= ( $trace_data['type'] ?? ' ' );
- $result .= ( $format )
- ? sprintf(
- '%s'
- . '( '
- . ') '
- . ' ',
- $trace_data['function']
- )
- : ($trace_data['function'] . '()');
+
+ if( $format ) {
+
+ $separator_pos = strrpos($trace_data['function'], '\\');
+
+ if( $separator_pos === false ) {
+ $result .= $this->formatter->formatSimplifiedFunctionStr(
+ $trace_data['function']
+ );
+ } else {
+ $result .= $this->formatter->formatNamespaceName(
+ $trace_data['function'],
+ ['func']
+ ) . '( '
+ . ') ';
+ }
+
+ } else {
+
+ $result .= ($trace_data['function'] . '()');
+ }
if( $format && $convert_links ) {
$result = $formatter->buildIdeHtmlLink(
$filename,
$result,
- ((int)$trace_data['line'] ?? null),
+ ( (int)$trace_data['line'] ?? null ),
class_names: ['file']
);
}
@@ -225,12 +238,19 @@ class_names: ['file']
if( is_object($arg) ) {
+ $class = $arg::class;
+ $formatted_class = $formatter->formatClassNameOrNamespace(
+ $class
+ );
$argument = ( $convert_links )
- ? $formatter->namespaceToIdeHtmlLink($arg::class)
- : $arg::class;
+ ? $formatter->namespaceToIdeHtmlLink(
+ $class,
+ text: $formatted_class
+ )
+ : $formatted_class;
if( !$argument ) {
- $argument = $arg::class;
+ $argument = $formatted_class;
}
$allow_html_entities = false;
@@ -238,7 +258,7 @@ class_names: ['file']
/* Don't attempt to export and show text for the following
types, eg. `var_export` will fail on large arrays containing
objects with circular reference, etc. */
- } elseif( is_array($arg) && is_resource($arg) ) {
+ } elseif( is_array($arg) || is_resource($arg) ) {
$argument = '';
@@ -249,11 +269,11 @@ class_names: ['file']
// String (can be file path or namespace name).
if(
- str_starts_with($argument, '\'')
- && str_ends_with($argument, '\'')
+ str_starts_with($argument, "'")
+ && str_ends_with($argument, "'")
) {
- $trimmed_arg = trim($argument, '\'');
+ $trimmed_arg = trim($argument, "'");
$length = strlen($trimmed_arg);
if( $formatter->isQualifiedPathname($trimmed_arg) ) {
@@ -273,12 +293,23 @@ class_names: ['file']
'\\',
$trimmed_arg
);
+
+ if( $format ) {
+ $namespace_formatted
+ = $formatter->formatClassNameOrNamespace(
+ $namespace
+ );
+ }
+
$argument = ( $convert_links )
? $formatter->namespaceToIdeHtmlLink(
$namespace,
- class_names: ['file']
+ class_names: ['file'],
+ text: $namespace_formatted
)
- : $namespace;
+ : ( ( $format )
+ ? $namespace_formatted
+ : $namespace );
$allow_html_entities = false;
}
diff --git a/src/lib/php-code-test-suite/OutputText/OutputTextFormatter.php b/src/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
index 4ac2819..2432b21 100644
--- a/src/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
+++ b/src/lib/php-code-test-suite/OutputText/OutputTextFormatter.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -18,6 +18,8 @@
namespace PCTS\OutputText;
+use PCTS\PhpTokens\EnhancedPhpToken;
+
class OutputTextFormatter {
/** Files with the following file formats will be shortened. */
@@ -123,11 +125,52 @@ public function formatPathname(
return ($pathname . $text_suffix);
}
- $text = ($this->shortenPathname($pathname) . $text_suffix);
+ return $this->formatPathnameWithText(
+ $pathname,
+ $this->shortenPathname($pathname),
+ $text_suffix,
+ $line_number,
+ $column_number,
+ $class_names
+ );
+ }
+
+ /**
+ * Formats qualified/verified pathname.
+ *
+ * @param string $pathname Path name reference.
+ * @param string $text Text representation of the pathname.
+ * @param string $suffix Text suffix to add after formatted text.
+ * @param int|null $line_number Line number.
+ * @param int|null $column_number Column number.
+ * @param array|null $class_names When links are used, add these classes.
+ * @return string If HTML formatting is enabled, HTML formatted text,
+ * otherwise just plain text
+ */
+ protected function formatPathnameWithText(
+ string $pathname,
+ string $text,
+ string $suffix = '',
+ ?int $line_number = null,
+ ?int $column_number = null,
+ ?array $class_names = null
+ ): string {
+
+ $file_exists = file_exists($pathname);
+
+ if( $this->format_html ) {
+ $path_classes = [];
+ if( !$file_exists ) {
+ $path_classes[] = 'no-file';
+ }
+ $text = self::formatPathnameAddWrappers($text, $path_classes);
+ }
+
+ $text = ($text . $suffix);
$is_link = (
$this->format_html
+ && $file_exists
&& $this->convert_links
- && file_exists($pathname)
);
return ( $is_link )
@@ -141,6 +184,36 @@ public function formatPathname(
: $text;
}
+ /** Adds outer and inner HTML wrappers to the given pathname. */
+ public static function formatPathnameAddWrappers(
+ string $pathname,
+ array $path_classes = [],
+ array $base_classes = []
+ ): string {
+
+ $basename = basename($pathname);
+ $basename_len = strlen($basename);
+ $extension = pathinfo($pathname, PATHINFO_EXTENSION);
+ $path_classes = ['path', ...$path_classes];
+ $base_classes = ['base', ...$base_classes];
+
+ if( $extension === 'php' ) {
+ $base_classes[] = 'ext-php';
+ }
+
+ return sprintf(
+ '',
+ implode(' ', $path_classes)
+ )
+ . substr($pathname, 0, -$basename_len)
+ . sprintf(
+ '%s ',
+ implode(' ', $base_classes),
+ substr($pathname, -$basename_len)
+ )
+ . ' ';
+ }
+
/** Tells if the given value is recognized as a qualified namespace. */
public function isQualifiedNamespace(
string $value
@@ -163,10 +236,7 @@ public function format(
): string {
$result = $this->shortenFilenamesAll($text);
-
- if( $this->convert_links ) {
- $result = $this->convertNamespacesToHtmlLinks($result);
- }
+ $result = $this->formatNamespaces($result);
return $result;
}
@@ -190,8 +260,8 @@ public function shortenFilenamesAll(
return $text;
}
- /** Converts all namespaces to HTML hyperlinks in the given text string. */
- public function convertNamespacesToHtmlLinks(
+ /** Formats all namespaces to HTML. */
+ public function formatNamespaces(
string $text,
?\Closure $match_handler = null
): string {
@@ -205,9 +275,10 @@ public function convertNamespacesToHtmlLinks(
array_keys($this->vendor_data)
);
- // Mind the "preceeded by" character group.
$regex_str = sprintf(
- '#(\s|^|\?|\(|"|\')((%s)[A-Za-z0-9\\\\]+)#m',
+ // Mind the "preceeded by" character group.
+ // Curly brackets "{}" are used to include "{closure}"
+ '#(\s|^|\?|\(|"|\'|\||:|&)((%s)[A-Za-z0-9_{}\\\\]+)#m',
implode('|', $vendor_names)
);
@@ -219,23 +290,62 @@ public function convertNamespacesToHtmlLinks(
foreach( $matches[2] as $index => $match ) {
- [$namespace, $line_number] = $match;
- $vendor_name = rtrim($matches[3][$index][0], '\\');
+ [$ns_name, $line_number] = $match;
+ [$vendor_name, $ns_start_pos] = $matches[3][$index];
+ $vendor_name = rtrim($vendor_name, '\\');
+ $ns_name_len = strlen($ns_name);
if( !$match_handler ) {
- $wrapper = $this->namespaceToIdeHtmlLink($namespace);
+ $ns_end_pos = ($ns_start_pos + $ns_name_len + $offset);
+ $is_func = (
+ isset($text[$ns_end_pos])
+ && $text[$ns_end_pos] === '('
+ );
+ $is_closure = (
+ !$is_func
+ && EnhancedPhpToken::namespaceToParts($ns_name)['base']
+ === '{closure}'
+ );
+ $ns_name_classes = ( !$is_func )
+ ? []
+ : ['func'];
+ if( !$is_func && !$is_closure ) {
+ $filename = $this->namespaceToFilename($ns_name);
+ if( !$filename || !file_exists($filename) ) {
+ $ns_name_classes[] = 'no-file';
+ $wrapper = $ns_name;
+ } elseif( $this->convert_links ) {
+ $wrapper = self::buildIdeHtmlLink(
+ $filename,
+ $ns_name
+ );
+ } else {
+ $wrapper = $ns_name;
+ }
+ } else {
+ $wrapper = $ns_name;
+ }
+ $wrapper = $this->formatClassNameOrNamespace(
+ $wrapper,
+ $ns_name_classes
+ );
+ if( $is_func || $is_closure ) {
+ $wrapper .= '( '
+ . ') ';
+ $ns_name_len += 2;
+ }
} else {
- $wrapper = $match_handler($namespace, $vendor_name);
+ $wrapper = $match_handler($ns_name, $vendor_name);
}
$text = substr_replace(
$text,
$wrapper,
- ((int)$match[1] + $offset),
- strlen($match[0])
+ ((int)$line_number + $offset),
+ $ns_name_len
);
- $offset += (strlen($wrapper) - strlen($match[0]));
+ $offset += (strlen($wrapper) - $ns_name_len);
}
}
@@ -258,8 +368,8 @@ public function shortenFilenamesByPath(
// Not preceeded by "file/".
'#(?editable_file_formats)
);
@@ -281,41 +391,47 @@ public function shortenFilenamesByPath(
. $relative_path
);
$filename_length = strlen($filename);
-
- $is_link = (
- $this->format_html
- && $this->convert_links
- && file_exists($filename)
+ $is_on_line = (
+ isset($matches[6][$index])
+ && !empty($matches[6][$index][0])
+ && $matches[6][$index][1] !== -1
+ );
+ $is_column_num = (
+ isset($matches[8][$index])
+ && !empty($matches[8][$index][0])
+ && $matches[8][$index][1] !== -1
+ );
+ $replace_text = $this->formatPathnameWithText(
+ $filename,
+ $text_relative_path,
+ line_number: match(true) {
+ $is_on_line => (int)$matches[6][$index][0],
+ $is_column_num => (int)$matches[8][$index][0],
+ default => null
+ },
+ class_names: ['file']
);
-
- $replace_text = ( $is_link )
- ? self::buildIdeHtmlLink(
- $filename,
- $text_relative_path,
- ( (int)$matches[6][$index][0] ?: null ),
- class_names: ['file']
- )
- : $text_relative_path;
-
$text = substr_replace(
$text,
$replace_text,
((int)$match[1] + $offset),
$filename_length
);
-
$offset_add = (strlen($replace_text) - $filename_length);
$offset += $offset_add;
// Captured line number.
if(
$this->format_html
- && isset($matches[6][$index])
- && !empty($matches[6][$index][0])
- && $matches[6][$index][1] !== -1
+ && ($is_on_line || $is_column_num)
) {
- [$line_number, $line_number_pos] = $matches[6][$index];
+ if( $is_on_line ) {
+ [$line_number, $line_number_pos] = $matches[6][$index];
+ } else {
+ [$line_number, $line_number_pos] = $matches[8][$index];
+ }
+
$line_number_length = strlen($line_number);
$replace_text = sprintf(
'%s ',
@@ -338,16 +454,21 @@ class_names: ['file']
/** Converts a namespace to IDE open file HTML hyperlink. */
public function namespaceToIdeHtmlLink(
string $namespace,
- ?array $class_names = null
+ ?array $class_names = null,
+ ?string $text = null,
): ?string {
if( !$filename = $this->namespaceToFilename($namespace) ) {
return null;
}
+ if( !file_exists($filename) ) {
+ return null;
+ }
+
return self::buildIdeHtmlLink(
$filename,
- $namespace,
+ ( $text ?: $namespace ),
class_names: $class_names
);
}
@@ -416,10 +537,7 @@ public function buildIdeHtmlLink(
) )
);
- $html_link .= ( $text )
- ? $text
- : $filename;
-
+ $html_link .= ( $text ?: $filename );
$html_link .= '';
return $html_link;
@@ -558,7 +676,6 @@ public static function parseIdeUriFormat(
'line' => $line_number,
'column' => $column_number,
];
-
$result = $mem = '';
$format_len = strlen($ide_uri_format);
$curly_stack = [];
@@ -683,4 +800,95 @@ public static function parseIdeUriFormat(
return $result;
}
+
+ /** HTML formats given class name - either fully qualified or keyword. */
+ public function formatClassNameOrNamespace(
+ string $string,
+ array $ns_name_classes = []
+ ): string {
+
+ $separator_pos = strrpos($string, '\\');
+
+ // Namespace
+ if( $separator_pos !== false ) {
+ return $this->formatNamespaceName($string, $ns_name_classes);
+ // Class name
+ } else {
+ return sprintf(
+ '%s ',
+ $string
+ );
+ }
+ }
+
+ /**
+ * HTML formats namespace name
+ *
+ * @param string $ns_name Namespace name.
+ * @param array $ns_name_classes Classes to add to namespace name wrapper.
+ * @return string HTML formatted namespace name.
+ */
+ public function formatNamespaceName(
+ string $ns_name,
+ array $ns_name_classes = []
+ ): string {
+
+ $separator_pos = strrpos($ns_name, '\\');
+
+ if( $separator_pos === false ) {
+ throw new \Exception(
+ "Namespace name must contain backward slash separator"
+ );
+ }
+
+ $base = substr($ns_name, ($separator_pos + 1));
+
+ if( $base === '{closure}' ) {
+ $base = self::getFormattedClosureString();
+ $ns_name_classes[] = 'closure';
+ }
+
+ $ns_name_classes = ['ns-name', ...$ns_name_classes];
+
+ return
+ sprintf(
+ '',
+ implode(' ', $ns_name_classes)
+ )
+ . substr($ns_name, 0, ($separator_pos + 1))
+ . sprintf(
+ '%s ',
+ $base
+ )
+ . ' ';
+ }
+
+ /** Returns HTML formatted debug string for closure. */
+ public static function getFormattedClosureString(): string {
+
+ return '{ '
+ . 'closure'
+ . '} ';
+ }
+
+ /** HTML formats a simplified function name string. */
+ public function formatSimplifiedFunctionStr( string $func_str ): string {
+
+ if( str_ends_with($func_str, '()') ) {
+ $func_str = substr($func_str, -2);
+ }
+
+ $func_format = '%s ';
+ $punc_html = '( '
+ . ') ';
+
+ if( $func_str === '{closure}' ) {
+ $func_str = self::getFormattedClosureString();
+ }
+
+ return (sprintf(
+ $func_format,
+ $func_str
+ ) . $punc_html);
+ }
}
diff --git a/src/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php b/src/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
index 3c2a911..f33bd2e 100644
--- a/src/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
+++ b/src/lib/php-code-test-suite/PhpErrors/ErrorCategoryEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php b/src/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
index 776009e..25aee47 100644
--- a/src/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
+++ b/src/lib/php-code-test-suite/PhpErrors/ErrorClassEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php b/src/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
index 6067b5f..2053265 100644
--- a/src/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
+++ b/src/lib/php-code-test-suite/PhpErrors/PhpErrorHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -247,7 +247,7 @@ public function richFormatErrorMessage(
)
);
$result .= '';
- $result .= 'Location ';
+ $result .= 'Location ';
$line_number_suffix = sprintf(
':%d ',
$line_number
@@ -264,7 +264,7 @@ class_names: ['file']
if( $error_type !== null ) {
- $result .= 'Type ';
+ $result .= 'Type ';
$result .= sprintf(
'%s ',
self::errorTypeToString($error_type)
@@ -324,24 +324,27 @@ public function richFormatException(
close_html_tags: false
);
- $exception_namespace = $exception::class;
-
- $result .= 'Error Class ';
+ $result .= 'Error Class ';
$result .= '';
+ $exception_class = $exception::class;
+ $class_formatted = $this->formatter->formatClassNameOrNamespace(
+ $exception_class
+ );
- if( $this->formatter->isQualifiedNamespace($exception_namespace) ) {
+ if( $this->formatter->isQualifiedNamespace($exception_class) ) {
$result .= $this->formatter->namespaceToIdeHtmlLink(
- $exception_namespace
+ $exception_class,
+ text: $class_formatted
);
} else {
- $result .= $exception_namespace;
+ $result .= $class_formatted;
}
$result .= ' ';
- $result .= 'Error Code ';
+ $result .= 'Error Code ';
$result .= '';
$result .= $exception->getCode();
$result .= ' ';
diff --git a/src/lib/php-code-test-suite/PhpTokens/BracketsEnum.php b/src/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
index bc17dee..daee8b2 100644
--- a/src/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
+++ b/src/lib/php-code-test-suite/PhpTokens/BracketsEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php b/src/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
index 9f6c55a..aaed0ff 100644
--- a/src/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
+++ b/src/lib/php-code-test-suite/PhpTokens/EnhancedPhpToken.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -45,6 +45,7 @@ class EnhancedPhpToken {
'noreturn',
'parent',
'self',
+ 'iterable',
'__COMPILER_HALT_OFFSET__',
];
@@ -95,8 +96,8 @@ public function isLeveled(): bool {
* @return bool True when found, and false when not found.
*/
public function lookAhead(
- array|string $while,
- array|string $until
+ int|array|string $while,
+ int|array|string $until
): bool {
$key = ($this->cache_key + 1);
@@ -171,25 +172,34 @@ public function isClassNameLookBehind(): bool {
}
$non_whitespace_tokens = [
- T_CLASS,
T_NEW,
T_INSTANCEOF,
T_EXTENDS,
T_INTERFACE,
+ T_IMPLEMENTS,
T_TRAIT,
T_ENUM,
// Traits
T_USE,
T_INSTEADOF,
- T_IMPLEMENTS,
];
- return $this->lookBehind([
+ $main_look_behind = $this->lookBehind([
+ T_WHITESPACE,
+ T_STRING,
+ T_CLASS,
+ ...$non_whitespace_tokens
+ ], [T_CLASS, ...$non_whitespace_tokens]);
+
+ #review: what role does comma exactly play?
+ $with_comma_look_behind = $this->lookBehind([
T_WHITESPACE,
',',
T_STRING,
...$non_whitespace_tokens
], $non_whitespace_tokens);
+
+ return $main_look_behind || $with_comma_look_behind;
}
/**
@@ -211,9 +221,11 @@ public function isNakedLookBehind( int $token_id ): bool {
/**
* Tells if current token might be a class name in catch clause.
*/
- public function isClassNameLookBehindForCatch(): bool {
+ public function isClassNameLookBehindForCatch(
+ int|string|array $is = T_STRING
+ ): bool {
- return ( !$this->token->is(T_STRING) )
+ return ( !$this->token->is($is) )
? false
: $this->lookBehind([
T_WHITESPACE,
@@ -252,6 +264,10 @@ public function isClassNameLookAhead(): bool {
return $this->lookAhead(
[T_WHITESPACE, T_VARIABLE, '|'],
[T_VARIABLE, '|'],
+ // Not preceeded by double colons.
+ ) && !$this->lookBehind(
+ [T_WHITESPACE, T_DOUBLE_COLON, T_PAAMAYIM_NEKUDOTAYIM],
+ [T_DOUBLE_COLON, T_PAAMAYIM_NEKUDOTAYIM]
);
}
@@ -687,10 +703,13 @@ public function getInnerHtml(): string {
*/
public function getNamespaceLastComponentType(): ?NUDTE {
- $type = NUDTE::CLASS_LIKE;
+ $type = NUDTE::CONSTANT;
+ $identified = false;
if( $context = $this->stream->getContext() ) {
+ $identified = true;
+
if( $context instanceof NamespaceUseDeclarationBuilder ) {
/* If there is a block statement in front, do not mark the last
@@ -706,6 +725,43 @@ public function getNamespaceLastComponentType(): ?NUDTE {
// Namespace definition will be presented as generic string.
$type = null;
+
+ } else {
+
+ $identified = false;
+ }
+
+ } elseif(
+ /* `isFunctionLookAhead` will not work here, because it can be a
+ "name" class token. */
+ $this->lookAhead([T_WHITESPACE, '('], '(')
+ && !$this->lookBehind([T_WHITESPACE, T_NEW], T_NEW)
+ ) {
+
+ $type = NUDTE::FUNCTION;
+ $identified = true;
+ }
+
+ if( !$identified ) {
+
+ $ns_name_parts = self::namespaceToParts($this->token->text);
+
+ if(
+ ($ns_name_parts['vendor'] && !$ns_name_parts['base'])
+ || (!$ns_name_parts['vendor'] && $ns_name_parts['base'])
+ || $this->lookAhead(
+ [T_WHITESPACE, T_DOUBLE_COLON],
+ T_DOUBLE_COLON
+ )
+ || $this->lookBehind([T_WHITESPACE, T_NEW], T_NEW)
+ || $this->lookBehind([T_WHITESPACE, T_USE], T_USE)
+ || $this->isClassNameLookBehindForCatch([
+ T_NAMESPACE,
+ T_NAME_QUALIFIED,
+ T_NAME_FULLY_QUALIFIED
+ ])
+ ) {
+ $type = NUDTE::CLASS_LIKE;
}
}
@@ -838,4 +894,38 @@ public static function getNamespaceInnerHtml(
return $result;
}
+
+ /** Returns parts for a given namespace name. */
+ public static function namespaceToParts( string $ns_name ): array {
+
+ $divider_pos = strpos($ns_name, '\\');
+
+ if( $divider_pos !== false ) {
+
+ $divider_pos_last = strrpos($ns_name, '\\');
+
+ return [
+ 'vendor' => substr($ns_name, 0, $divider_pos),
+ 'parts' => ($divider_pos !== $divider_pos_last)
+ ? explode(
+ '\\',
+ substr(
+ $ns_name,
+ ($divider_pos + 1),
+ $divider_pos_last - ($divider_pos + 1)
+ )
+ )
+ : [],
+ 'base' => substr($ns_name, ($divider_pos_last + 1)),
+ ];
+
+ } else {
+
+ return [
+ 'vendor' => $ns_name,
+ 'parts' => [],
+ 'base' => '',
+ ];
+ }
+ }
}
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
index cb1a3eb..8f551b3 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
index 7f69f11..2bd7f1e 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDeclaration.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
index e9f4744..ab761c7 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
index 0289e7f..22c7a46 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
index fed90ea..c2bdb0f 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AbstractStatement.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
index 392ab45..cfb50f8 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php b/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
index 1ce5d67..72304da 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/AnonymousFunctionDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
index aef187f..d979999 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/ArrowAnonymousFunctionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php b/src/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
index 303bdfb..9194c22 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/CategoryHintInterface.php
@@ -11,7 +11,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php b/src/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
index 24de334..606aad9 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/CompoundStatement.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php b/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
index ace2630..dff3d66 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
index 6a74081..e548f1a 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/FunctionDefinitionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
index aaed27c..6f36c7b 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinition.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
index d948a05..b733146 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceDefinitionBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
index 71e5aee..bb9f664 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclaration.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
index 2dc7951..206ab94 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationBuilder.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
index e472619..de985b0 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/NamespaceUseDeclarationTypeEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php b/src/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
index 1651099..1015ef8 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Language/OnFinishedHookTrait.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php b/src/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
index af21e05..9da4daf 100644
--- a/src/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
+++ b/src/lib/php-code-test-suite/PhpTokens/PhpTokenCategoryEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/PlacementEnum.php b/src/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
index 4c52fac..f21074d 100644
--- a/src/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
+++ b/src/lib/php-code-test-suite/PhpTokens/PlacementEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/PhpTokens/Tokenizer.php b/src/lib/php-code-test-suite/PhpTokens/Tokenizer.php
index bbaa995..b02a91b 100644
--- a/src/lib/php-code-test-suite/PhpTokens/Tokenizer.php
+++ b/src/lib/php-code-test-suite/PhpTokens/Tokenizer.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/utilities/AbstractHandler.php b/src/lib/php-code-test-suite/utilities/AbstractHandler.php
index 3ff47db..620fb7b 100644
--- a/src/lib/php-code-test-suite/utilities/AbstractHandler.php
+++ b/src/lib/php-code-test-suite/utilities/AbstractHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/utilities/ClosureHandler.php b/src/lib/php-code-test-suite/utilities/ClosureHandler.php
index b168f56..7a6b3a8 100644
--- a/src/lib/php-code-test-suite/utilities/ClosureHandler.php
+++ b/src/lib/php-code-test-suite/utilities/ClosureHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/utilities/IncludeHandler.php b/src/lib/php-code-test-suite/utilities/IncludeHandler.php
index 7685b0c..5011680 100644
--- a/src/lib/php-code-test-suite/utilities/IncludeHandler.php
+++ b/src/lib/php-code-test-suite/utilities/IncludeHandler.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/php-code-test-suite/utilities/utilities.php b/src/lib/php-code-test-suite/utilities/utilities.php
index d3c042f..b1215f5 100644
--- a/src/lib/php-code-test-suite/utilities/utilities.php
+++ b/src/lib/php-code-test-suite/utilities/utilities.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/Autoload.php b/src/lib/project-directory/Autoload.php
index 29c12bb..45d6b81 100644
--- a/src/lib/project-directory/Autoload.php
+++ b/src/lib/project-directory/Autoload.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/BranchedTestDirectory.php b/src/lib/project-directory/BranchedTestDirectory.php
index ff13508..97f17de 100644
--- a/src/lib/project-directory/BranchedTestDirectory.php
+++ b/src/lib/project-directory/BranchedTestDirectory.php
@@ -12,7 +12,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/DemoSpecialComment.php b/src/lib/project-directory/DemoSpecialComment.php
index 20d8a41..7309644 100644
--- a/src/lib/project-directory/DemoSpecialComment.php
+++ b/src/lib/project-directory/DemoSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/FileIterator.php b/src/lib/project-directory/FileIterator.php
index 97cec01..069708e 100644
--- a/src/lib/project-directory/FileIterator.php
+++ b/src/lib/project-directory/FileIterator.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/FileTrait.php b/src/lib/project-directory/FileTrait.php
index a91cda4..e93f3c6 100644
--- a/src/lib/project-directory/FileTrait.php
+++ b/src/lib/project-directory/FileTrait.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/LinkSpecialComment.php b/src/lib/project-directory/LinkSpecialComment.php
index 330586e..192a3ca 100644
--- a/src/lib/project-directory/LinkSpecialComment.php
+++ b/src/lib/project-directory/LinkSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/MainDirectoriesEnum.php b/src/lib/project-directory/MainDirectoriesEnum.php
index 615e0c8..f58f558 100644
--- a/src/lib/project-directory/MainDirectoriesEnum.php
+++ b/src/lib/project-directory/MainDirectoriesEnum.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/PlaygroundFile.php b/src/lib/project-directory/PlaygroundFile.php
index 28b846a..bbcb2ed 100644
--- a/src/lib/project-directory/PlaygroundFile.php
+++ b/src/lib/project-directory/PlaygroundFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/ProjectDirectory.php b/src/lib/project-directory/ProjectDirectory.php
index a0b0bc2..638bb7c 100644
--- a/src/lib/project-directory/ProjectDirectory.php
+++ b/src/lib/project-directory/ProjectDirectory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/ProjectFile.php b/src/lib/project-directory/ProjectFile.php
index a0d3478..67425a8 100644
--- a/src/lib/project-directory/ProjectFile.php
+++ b/src/lib/project-directory/ProjectFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
@@ -188,7 +188,6 @@ public function replaceByCoords(
}
$data = ($before_portion . $replacement);
-
$file_size = $this->file->getSize();
if( $coords[1] < $file_size ) {
@@ -400,6 +399,39 @@ public function rebuildSpecialComment(
}
}
+ /** Removes given special comment. */
+ public function removeSpecialComment(
+ SpecialComment $special_comment
+ ): ?bool {
+
+ if( $this->file->getSize() && $this->isSupportedFileType() ) {
+
+ $coords = $this->containsSpecialComment($special_comment);
+
+ if( !$coords ) {
+ return null;
+ }
+
+ $this->file->rewind();
+ clearstatcache();
+
+ while(
+ $this->file->fseek($coords[1]) === 0
+ && ($char = $this->file->fread(1)) !== false
+ && ( $char === "\r" || $char === "\n" )
+ ) {
+ $coords[1]++;
+ }
+
+ return $this->replaceByCoords($coords, '');
+
+ // File is empty or unsupported.
+ } else {
+
+ return null;
+ }
+ }
+
/** Rebuilds all special comments. */
public function rebuildAllSpecialCommentLines(): ?bool {
@@ -422,6 +454,28 @@ public function rebuildAllSpecialCommentLines(): ?bool {
}
}
+ /** Removes all special comments. */
+ public function removeAllSpecialCommentLines(): ?bool {
+
+ if( $this->file->getSize() && $this->isSupportedFileType() ) {
+
+ foreach( $this->special_comments as $special_comment ):
+
+ if( $this->removeSpecialComment($special_comment) === false ) {
+ return false;
+ }
+
+ endforeach;
+
+ return true;
+
+ // File is empty or unsupported.
+ } else {
+
+ return null;
+ }
+ }
+
/** Retrieves full contents of this file. */
public function getContents(): string|false {
diff --git a/src/lib/project-directory/ProjectFileObject.php b/src/lib/project-directory/ProjectFileObject.php
index d7e0beb..c2d3e75 100644
--- a/src/lib/project-directory/ProjectFileObject.php
+++ b/src/lib/project-directory/ProjectFileObject.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/ProjectFileObjectFactory.php b/src/lib/project-directory/ProjectFileObjectFactory.php
index fdc7e1b..4a055b7 100644
--- a/src/lib/project-directory/ProjectFileObjectFactory.php
+++ b/src/lib/project-directory/ProjectFileObjectFactory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/ProjectRootDirectory.php b/src/lib/project-directory/ProjectRootDirectory.php
index 432cc19..9233f25 100644
--- a/src/lib/project-directory/ProjectRootDirectory.php
+++ b/src/lib/project-directory/ProjectRootDirectory.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/RecursiveFileIterator.php b/src/lib/project-directory/RecursiveFileIterator.php
index 4f9336e..f347cee 100644
--- a/src/lib/project-directory/RecursiveFileIterator.php
+++ b/src/lib/project-directory/RecursiveFileIterator.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/SourceFile.php b/src/lib/project-directory/SourceFile.php
index 6926e21..8c80326 100644
--- a/src/lib/project-directory/SourceFile.php
+++ b/src/lib/project-directory/SourceFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/SourceSpecialComment.php b/src/lib/project-directory/SourceSpecialComment.php
index 71b48f4..7a10c56 100644
--- a/src/lib/project-directory/SourceSpecialComment.php
+++ b/src/lib/project-directory/SourceSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/SpecialComment.php b/src/lib/project-directory/SpecialComment.php
index 5e02ef6..0524d32 100644
--- a/src/lib/project-directory/SpecialComment.php
+++ b/src/lib/project-directory/SpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/StaticFile.php b/src/lib/project-directory/StaticFile.php
index e8b93ab..93590cb 100644
--- a/src/lib/project-directory/StaticFile.php
+++ b/src/lib/project-directory/StaticFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/lib/project-directory/StaticSpecialComment.php b/src/lib/project-directory/StaticSpecialComment.php
index 58f6912..b125db4 100644
--- a/src/lib/project-directory/StaticSpecialComment.php
+++ b/src/lib/project-directory/StaticSpecialComment.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.4
*/
diff --git a/src/lib/project-directory/TestFile.php b/src/lib/project-directory/TestFile.php
index 8147aaf..2fcbbf4 100644
--- a/src/lib/project-directory/TestFile.php
+++ b/src/lib/project-directory/TestFile.php
@@ -10,7 +10,7 @@
* @license MIT License
* @copyright Copyright (c) 2023 LWIS Technologies
* (https://www.lwis.net/)
- * @version 1.0.6
+ * @version 1.0.7
* @since 1.0.0
*/
diff --git a/src/web/api/directory-listing.php b/src/web/api/directory-listing.php
index d901187..e30e81d 100644
--- a/src/web/api/directory-listing.php
+++ b/src/web/api/directory-listing.php
@@ -47,7 +47,6 @@
}
$charset = 'UTF-8';
-$transliterator = 'Any-Latin; Latin-ASCII';
$has_search_query = ( $search_query !== null );
if( !$has_search_query ) {
@@ -58,12 +57,17 @@
} else {
$file_iterator = $project_file_object->getRecursiveIterator();
-
+ $has_transliterator = function_exists('transliterator_transliterate');
+ $transliterator = 'Any-Latin; Latin-ASCII';
$comparable_search_query = mb_strtolower($search_query, $charset);
- $comparable_search_query = transliterator_transliterate(
- $transliterator,
- $comparable_search_query
- );
+
+ if( $has_transliterator ) {
+
+ $comparable_search_query = transliterator_transliterate(
+ $transliterator,
+ $comparable_search_query
+ );
+ }
}
$data = [];
@@ -91,10 +95,13 @@
$charset
);
- $comparable_searchable_str = transliterator_transliterate(
- $transliterator,
- $comparable_searchable_str
- );
+ if( $has_transliterator ) {
+
+ $comparable_searchable_str = transliterator_transliterate(
+ $transliterator,
+ $comparable_searchable_str
+ );
+ }
if(
mb_strpos(
diff --git a/src/web/api/file-handler.php b/src/web/api/file-handler.php
index b4dd1ae..529caa0 100644
--- a/src/web/api/file-handler.php
+++ b/src/web/api/file-handler.php
@@ -38,6 +38,9 @@
);
}
+$force_source = get_value_exists('force_source', '0');
+$force_source = ( is_numeric($force_source) && $force_source === '1' );
+
/**
* Enumerates view handler names.
*/
@@ -46,7 +49,7 @@ enum ViewHandlersEnum: string {
case OUTPUT_CODE_PARTS = 'demo-output';
}
-$handler_name = ( $project_file_object instanceof TestFile )
+$handler_name = ( ($project_file_object instanceof TestFile) && !$force_source )
? ViewHandlersEnum::OUTPUT_CODE_PARTS
: ViewHandlersEnum::SOURCE_CODE_PARTS;
@@ -225,7 +228,7 @@ function( string $value ) use( &$i ): string {
$inner_html,
$known_vendors_by_base
);
- $inner_html = $formatter->convertNamespacesToHtmlLinks(
+ $inner_html = $formatter->formatNamespaces(
$inner_html,
function(
string $namespace,
diff --git a/src/web/api/projects-listing.php b/src/web/api/projects-listing.php
index eb401cd..d3d5ec4 100644
--- a/src/web/api/projects-listing.php
+++ b/src/web/api/projects-listing.php
@@ -55,16 +55,17 @@
$search_query = get_value_exists('project_search_query');
$has_search_query = ( $search_query !== null );
-$search_query_limit = 100;
$charset = 'UTF-8';
$transliterator = 'Any-Latin; Latin-ASCII';
if( $has_search_query ) {
- $search_query = transliterator_transliterate(
- $transliterator,
- mb_strtolower($search_query, $charset)
- );
+ $search_query_limit = 100;
+ $has_transliterator = function_exists('transliterator_transliterate');
+ $search_query_lc = mb_strtolower($search_query, $charset);
+ $search_query = ( $has_transliterator )
+ ? transliterator_transliterate($transliterator, $search_query_lc)
+ : $search_query_lc;
if( mb_strlen($search_query) > $search_query_limit ) {
send_error(
@@ -77,6 +78,10 @@
$index = 0;
$select_from = (($page_number - 1) * $entries_per_page + 1);
$select_to = ($select_from + $entries_per_page - 1);
+$config_file_ending = (DIRECTORY_SEPARATOR
+ . ProjectRootDirectory::SYS_CONFIG_DIR_NAME
+ . DIRECTORY_SEPARATOR
+ . ProjectRootDirectory::SYS_CONFIG_FILE_NAME);
foreach( $file_iterator as $fileinfo ) {
@@ -85,20 +90,16 @@
if(
$fileinfo->isDir()
&& !str_starts_with($file_name, '.')
- && file_exists(
- $fileinfo->getPathname()
- . DIRECTORY_SEPARATOR
- . ProjectRootDirectory::SYS_CONFIG_DIR_NAME
- . DIRECTORY_SEPARATOR
- . ProjectRootDirectory::SYS_CONFIG_FILE_NAME
- )
+ && file_exists($fileinfo->getPathname() . $config_file_ending)
&& (
!$has_search_query
|| mb_strpos(
- transliterator_transliterate(
- $transliterator,
- mb_strtolower($file_name, $charset)
- ),
+ ( ( $has_transliterator )
+ ? transliterator_transliterate(
+ $transliterator,
+ mb_strtolower($file_name, $charset)
+ )
+ : mb_strtolower($file_name, $charset) ),
$search_query,
encoding: $charset
) !== false
@@ -143,7 +144,7 @@
$data[] = [
'title' => $title,
'pathname' => '/foo/bar',
- 'url' => 'https://localhost/',
+ 'url' => 'http://localhost/',
];
}
}
diff --git a/src/web/api/rebuild-special-comments.php b/src/web/api/rebuild-special-comments.php
index df7d209..64af835 100644
--- a/src/web/api/rebuild-special-comments.php
+++ b/src/web/api/rebuild-special-comments.php
@@ -26,7 +26,6 @@
!($project_file_object instanceof SourceFile)
&& !($project_file_object instanceof TestFile)
) {
-
send_error(
"File $path does not represent a source, or a test file"
);
diff --git a/src/web/api/remove-special-comments.php b/src/web/api/remove-special-comments.php
new file mode 100644
index 0000000..6fabd46
--- /dev/null
+++ b/src/web/api/remove-special-comments.php
@@ -0,0 +1,42 @@
+find($path);
+
+if( !$project_file_object ) {
+ send_error("File with path $path was not found");
+}
+
+if(
+ !($project_file_object instanceof SourceFile)
+ && !($project_file_object instanceof TestFile)
+) {
+ send_error(
+ "File $path does not represent a source, or a test file"
+ );
+}
+
+$remove_result = $project_file_object->removeAllSpecialCommentLines();
+
+if( $remove_result === false ) {
+ send_error("Could not remove special comment lines");
+} elseif( $remove_result === null ) {
+ send_error("There was nothing to remove");
+} else {
+ send_success([]);
+}
diff --git a/src/web/app/assets/css/components/accessories.css b/src/web/app/assets/css/components/accessories.css
index 4f4c92b..fe0e160 100644
--- a/src/web/app/assets/css/components/accessories.css
+++ b/src/web/app/assets/css/components/accessories.css
@@ -14,8 +14,8 @@
.type-file,
.type-dir,
.i-menu,
- .i-open-lo,
- .i-disc-lo,
+ .i-std-lo-lhs,
+ .i-std-lo,
.tgl-lo,
.tgl-word-wrap-btn,
.scr.welcome h1,
@@ -57,10 +57,10 @@
.type-dir > :first-child::before,
.type-dir > :first-child::after,
.i-menu::before,
- .i-open-lo::before,
- .i-open-lo::after,
- .i-disc-lo::before,
- .i-disc-lo::after,
+ .i-std-lo-lhs::before,
+ .i-std-lo-lhs::after,
+ .i-std-lo::before,
+ .i-std-lo::after,
.tgl-lo::before,
.tgl-lo::after,
.tgl-word-wrap-btn::before,
@@ -81,7 +81,7 @@
/* Medium Length Rightwards Arrow */
.i-md-rt-arw,
- .cont-btn:not(.waiting) {
+ .cont-btn:not(.wtng) {
--icon-size: 20px;
--wing-size: 10px;
}
@@ -98,7 +98,11 @@
}
.i-md-rt-arw::after,
- .cont-btn:not(.wtng)::after {
+ .cont-btn:not(.wtng)::after,
+ .i-run::before,
+ [data-handler="demo-output"] .tgl-view-btn::before,
+ .i-code::before,
+ [data-handler="source-code"] .tgl-view-btn::before {
top: calc(50% + var(--icon-weight-half));
left: calc(50% + var(--icon-size-half) - var(--wing-size)
+ var(--icon-weight-half));
@@ -134,46 +138,58 @@
/* Enter & Exit Fullscreen */
:is(.i-go-fscr, .i-exit-fscr, .tgl-fscr-btn) {
- --icon-size: 10px;
- --icon-offset: 1px;
+ --wing-size: 8px;
+ --icon-size: 20px;
+ /* Calculated */
+ --icon-size-max: max(calc(var(--wing-size) * 2), var(--icon-size));
}
:is(.i-go-fscr, .i-exit-fscr, .tgl-fscr-btn)::before,
:is(.i-go-fscr, .i-exit-fscr, .tgl-fscr-btn)::after {
- width: var(--icon-size);
- height: var(--icon-size);
- border: solid var(--icon-weight) var(--icon-color);
+ top: calc(50% - var(--icon-size-half));
+ left: calc(50% - var(--icon-size-half));
border-radius: var(--icon-weight-half);
+ background-color: var(--icon-color);
}
:is(.i-go-fscr, .i-exit-fscr, .tgl-fscr-btn)::before {
- bottom: calc(50% + var(--icon-offset));
- left: calc(50% + var(--icon-offset));
- border-width: var(--icon-weight) var(--icon-weight) 0 0;
+ width: var(--wing-size);
+ height: var(--icon-weight);
+ box-shadow: var(--offset1) 0 0,
+ 0 var(--offset2) 0,
+ var(--offset1) var(--offset2) 0;
}
:is(.i-go-fscr, .i-exit-fscr, .tgl-fscr-btn)::after {
- top: calc(50% + var(--icon-offset));
- right: calc(50% + var(--icon-offset));
- border-width: 0 0 var(--icon-weight) var(--icon-weight);
+ width: var(--icon-weight);
+ height: var(--wing-size);
+ box-shadow: var(--offset2) 0 0,
+ 0 var(--offset1) 0,
+ var(--offset2) var(--offset1) 0;
}
- .i-exit-fscr::before,
- body:fullscreen .tgl-fscr-btn::before {
- border-width: 0 0 var(--icon-weight) var(--icon-weight);
+ .i-go-fscr,
+ .tgl-fscr-btn {
+ --offset1: calc(var(--icon-size-max) - var(--wing-size));
+ --offset2: calc(var(--icon-size-max) - var(--icon-weight));
}
- body:-webkit-full-screen .tgl-fscr-btn::before {
- border-width: 0 0 var(--icon-weight) var(--icon-weight);
+ .i-exit-fscr,
+ body:fullscreen .tgl-fscr-btn {
+ /* Calculated */
+ --inner-wing-size: calc(var(--wing-size) - var(--icon-weight));
+ --offset1: calc(var(--icon-size-max) - var(--wing-size));
+ --offset2: calc(var(--offset1) - var(--inner-wing-size));
}
- .i-exit-fscr::after,
- body:fullscreen .tgl-fscr-btn::after {
- border-width: var(--icon-weight) var(--icon-weight) 0 0;
+ .i-exit-fscr::before,
+ body:fullscreen .tgl-fscr-btn::before {
+ margin-top: var(--inner-wing-size);
}
- body:-webkit-full-screen .tgl-fscr-btn::after {
- border-width: var(--icon-weight) var(--icon-weight) 0 0;
+ .i-exit-fscr::after,
+ body:fullscreen .tgl-fscr-btn::after {
+ margin-left: var(--inner-wing-size);
}
/* Search */
@@ -529,9 +545,30 @@
background-clip: content-box;
}
- /* Open Layout */
+ /* Standard Layout */
- .i-open-lo {
+ .i-std-lo {
+ --icon-width: 20px;
+ --icon-height: 14px;
+ --stroke-size: 2px;
+ }
+
+ .i-std-lo::before {
+ top: 50%;
+ left: 50%;
+ width: var(--icon-width);
+ height: var(--icon-height);
+ padding-top: var(--stroke-size);
+ transform: translate(-50%,-50%);
+ border-top: solid var(--stroke-size) var(--icon-color);
+ background-color: var(--icon-color);
+ background-clip: content-box;
+ }
+
+ /* Standard Layout With Sidebar */
+
+ .i-std-lo-lhs,
+ .i-std-lo-rhs {
--icon-width: 20px;
--icon-height: 14px;
--stroke-size: 2px;
@@ -539,7 +576,8 @@
--stroke-size-double: calc(var(--stroke-size) * 2);
}
- .i-open-lo::before {
+ .i-std-lo-lhs::before,
+ .i-std-lo-rhs::before {
top: 50%;
left: 50%;
transform: translate(-50%, calc(0px - var(--icon-height) / 2));
@@ -548,36 +586,29 @@
background-color: var(--icon-color);
}
- .i-open-lo::after {
+ .i-std-lo-lhs::after,
+ .i-std-lo-rhs::after {
top: 50%;
left: 50%;
transform: translate(-50%, calc(0px - (var(--icon-height) / 2 - var(--stroke-size-double))));
width: var(--icon-width);
height: calc(var(--icon-height) - var(--stroke-size-double));
- border-left: solid var(--stroke-size-double) var(--icon-color);
- padding-left: var(--stroke-size);
background-color: var(--icon-color);
background-clip: content-box;
}
- /* Discrete Layout */
+ /* Standard Layout With LHS Sidebar */
- .i-disc-lo {
- --icon-width: 20px;
- --icon-height: 14px;
- --stroke-size: 2px;
+ .i-std-lo-lhs::after {
+ border-left: solid var(--stroke-size-double) var(--icon-color);
+ padding-left: var(--stroke-size);
}
- .i-disc-lo::before {
- top: 50%;
- left: 50%;
- width: var(--icon-width);
- height: var(--icon-height);
- padding-top: var(--stroke-size);
- transform: translate(-50%,-50%);
- border-top: solid var(--stroke-size) var(--icon-color);
- background-color: var(--icon-color);
- background-clip: content-box;
+ /* Standard Layout With RHS Sidebar */
+
+ .i-std-lo-rhs::after {
+ border-right: solid var(--stroke-size-double) var(--icon-color);
+ padding-right: var(--stroke-size);
}
/* No Word Wrap */
@@ -722,6 +753,60 @@
content: 'i';
}
+ /* Run */
+
+ .i-run,
+ [data-handler="demo-output"] .tgl-view-btn {
+ --icon-width: 25px;
+ --icon-height: 20px;
+ --line-size: 15px;
+ --wing-size: 10px;
+ /* Calculated */
+ --icon-height-half: calc(var(--icon-height) / 2);
+ }
+
+ .i-run::before,
+ [data-handler="demo-output"] .tgl-view-btn::before {
+ left: calc(50% - var(--icon-width) / 2);
+ }
+
+ .i-run::after,
+ [data-handler="demo-output"] .tgl-view-btn::after {
+ top: calc(50% + (var(--icon-height-half) - var(--icon-weight)));
+ left: calc(50% + (var(--icon-width) / 2 - var(--line-size)));
+ width: var(--line-size);
+ height: var(--icon-weight);
+ background-color: var(--icon-color);
+ border-radius: var(--icon-weight-half);
+ }
+
+ /* Code */
+
+ .i-code,
+ [data-handler="source-code"] .tgl-view-btn {
+ --wing-size: 10px;
+ }
+
+ .i-code::before,
+ [data-handler="source-code"] .tgl-view-btn::before {
+ top: 50%;
+ left: calc(50% - 11px);
+ border-width: 2px 0 0 2px;
+ transform: rotate(-45deg);
+ transform-origin: 0 0;
+ }
+
+ .i-code::after,
+ [data-handler="source-code"] .tgl-view-btn::after {
+ top: calc(50% - 10px);
+ left: calc(50% - var(--icon-weight-half) + 5px);
+ width: var(--icon-weight);
+ height: 20px;
+ background-color: var(--icon-color);
+ border-radius: var(--icon-weight-half);
+ transform: rotate(30deg);
+ }
+
/* Compact Buttons */
diff --git a/src/web/app/assets/css/components/app-code-message.css b/src/web/app/assets/css/components/app-code-message.css
index 49588a8..e53d3d3 100644
--- a/src/web/app/assets/css/components/app-code-message.css
+++ b/src/web/app/assets/css/components/app-code-message.css
@@ -1,5 +1,41 @@
@import "../../../../assets/css/code-message.css";
+/* Code Message */
+
+.code-msg {
+ padding: 20px 12px;
+ border-width: 1px 0;
+}
+
+.code-msg .code-msg {
+ margin-top: 1em;
+ border-width: 1px;
+}
+
+.code-msg .arg-l > li::before {
+ background-color: var(--mg-color);
+}
+
+.code-msg .stk-tr-l > li::marker {
+ color: var(--bg-color-restrained);
+}
+
+:root[data-theme="light"] .code-msg .path .base {
+ color: #669321;
+}
+
+:root[data-theme="dark"] .code-msg .path .base {
+ color: #669321;
+}
+
+:root[data-theme="light"] .code-msg .path .base.ext-php {
+ color: #9f74c4;
+}
+
+:root[data-theme="dark"] .code-msg .path .base.ext-php {
+ color: #9f74c4;
+}
+
/* Output */
.o {
@@ -22,22 +58,8 @@
text-decoration-style: solid;
}
-/* Code Message */
-
-.code-msg {
- padding: 20px 12px;
- border-width: 1px 0;
-}
-
-.code-msg .code-msg {
- margin-top: 1em;
- border-width: 1px;
-}
-
-.code-msg .arg-l > li::before {
- background-color: var(--mg-color);
-}
-
-.code-msg .stk-tr-l > li::marker {
- color: var(--bg-color-restrained);
+.o > .code-msg {
+ font: 16px/1.5 system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
+ Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',
+ sans-serif;
}
\ No newline at end of file
diff --git a/src/web/app/assets/css/components/code-php-highlight.css b/src/web/app/assets/css/components/code-php-highlight.css
index f2fdcc7..6a6d1c7 100644
--- a/src/web/app/assets/css/components/code-php-highlight.css
+++ b/src/web/app/assets/css/components/code-php-highlight.css
@@ -235,7 +235,8 @@
/* Issues */
/* Namespace that is not backed by a file */
-.code-php .namespace.no-file {
+.code-php .namespace.no-file,
+.code-php .class-name.no-file {
text-decoration: underline var(--bg-color-restrained, #666) wavy;
-webkit-text-decoration: underline var(--bg-color-restrained, #666) wavy;
text-decoration-skip-ink: auto;
diff --git a/src/web/app/assets/scripts/app.js b/src/web/app/assets/scripts/app.js
index b0c2970..261914f 100644
--- a/src/web/app/assets/scripts/app.js
+++ b/src/web/app/assets/scripts/app.js
@@ -205,7 +205,7 @@ function markSubstringsInString(
}
return stringWrap(
- string,
+ string.normalize('NFC'),
positions,
searchString.length,
before,
@@ -244,6 +244,20 @@ function writeToClipboard(text, onSuccess, onFailure) {
});
}
+/**
+ * Checks if the currently focused element is an active form control.
+ * @returns {boolean} True if the active element is an input, textarea, or
+ * select; otherwise, false.
+ */
+function isActiveFormControl() {
+ return document.activeElement !== null
+ && (
+ document.activeElement instanceof HTMLInputElement
+ || document.activeElement instanceof HTMLTextAreaElement
+ || document.activeElement instanceof HTMLSelectElement
+ );
+}
+
/**
* Resets the app title in the document
*/
@@ -981,12 +995,20 @@ function SearchableApiListing(
});
});
this.listingBody.addEventListener('scroll', () => {
- if (this.hasMorePages() && this.hasReachedScrollThreshold()) {
+ if (
+ // Ignore scroll when awaiting previous response
+ !this.scrollOccupied
+ && this.hasMorePages()
+ && this.hasReachedScrollThreshold()
+ ) {
+ this.scrollOccupied = true;
this.nextPageRequest().then(payload => {
if (payload) {
this.appendGroupContents(payload);
this.populateStateData(payload);
}
+ }).finally(() => {
+ this.scrollOccupied = false;
});
}
});
@@ -998,9 +1020,12 @@ Object.assign(SearchableApiListing.prototype, {
? new URL(endpointUrl)
: endpointUrl;
},
- async fillUpContents() {
- if (this.getRemainingSpace()) {
+ async fillUpContents(onPayload, willReplace = false) {
+ if (willReplace || this.getRemainingSpace()) {
return this.nextPageRequestUntil(payload => {
+ if (typeof onPayload === 'function') {
+ onPayload(payload);
+ }
this.populateStateData(payload);
this.appendGroupContents(payload);
return this.hasMorePages() && this.getRemainingSpace();
@@ -1130,13 +1155,15 @@ Object.assign(SearchableApiListing.prototype, {
});
},
async nextPageRequestUntil(untilHandler) {
- return this.request({
- pageNumber: (this.pageNumber + 1)
- }).then(async payload => {
- if (payload !== false && untilHandler(payload)) {
- await this.nextPageRequestUntil(untilHandler);
- }
- });
+ if (this.pageNumber === 0 || this.hasMorePages()) {
+ return this.request({
+ pageNumber: (this.pageNumber + 1)
+ }).then(async payload => {
+ if (payload !== false && untilHandler(payload)) {
+ await this.nextPageRequestUntil(untilHandler);
+ }
+ });
+ }
},
bindSearchInput() {
this.searchInput.addEventListener('input', () => {
@@ -1152,7 +1179,9 @@ Object.assign(SearchableApiListing.prototype, {
if (data.length) {
this.populateStateData(payload);
this.replaceGroupContents(payload);
- this.fillUpContents();
+ if (payload.maxPages > payload.pageNumber) {
+ this.fillUpContents();
+ }
// No results.
} else {
this.flushGroupContents();
@@ -1197,9 +1226,12 @@ Object.assign(SearchableApiListing.prototype, {
}));
}
this.setEndpointUrl(endpointUrl);
- this.flushGroupContents();
this.pageNumber = 0;
- return this.fillUpContents();
+ return this.fillUpContents(payload => {
+ if (payload && payload.pageNumber == '1') {
+ this.flushGroupContents();
+ }
+ }, true);
}
});
@@ -1923,6 +1955,7 @@ const genericScreen = {
'main',
'project_search_query',
'file_search_query',
+ 'force_source',
],
menuItems: [
{
@@ -1991,6 +2024,7 @@ const genericScreen = {
},
],
abortControllers: new Set(),
+ keyboardShortcuts: {},
/**
* Amends the location to contain given state parameters
* @param {object} params - State parameters
@@ -2094,26 +2128,6 @@ const genericScreen = {
onClose(callback) {
this.onCloseCallbacks.add(callback);
},
- /**
- * Closes currently active screen
- * @returns {null|boolean} Null when there is nothing to be closed
- */
- close() {
- if (!this.isLoaded) {
- return null;
- }
- console.log(`closing ${this.name} screen`);
- this.clearAbortControllers();
- this.container.remove();
- document.body.removeAttribute('data-current-screen-name');
- this.isLoaded = false;
- if (this.onCloseCallbacks.size) {
- this.onCloseCallbacks.forEach(callback => {
- callback();
- });
- }
- return true;
- },
/**
* Adds the screen container to the document body and makes it globally
* available
@@ -2133,6 +2147,38 @@ const genericScreen = {
finishLoading() {
this.isLoaded = true;
currentLoadedScreen = this;
+ const keyboardShortcuts = {
+ ...genericScreen.keyboardShortcuts,
+ ...this.keyboardShortcuts
+ };
+ for (const [name, method] of Object.entries(keyboardShortcuts)) {
+ this.keyboardShortcuts[name] = method.bind(this);
+ document.addEventListener('keydown', this.keyboardShortcuts[name]);
+ }
+ },
+ /**
+ * Closes currently active screen
+ * @returns {null|boolean} Null when there is nothing to be closed
+ */
+ close() {
+ if (!this.isLoaded) {
+ return null;
+ }
+ console.log(`closing ${this.name} screen`);
+ this.clearAbortControllers();
+ this.container.remove();
+ document.body.removeAttribute('data-current-screen-name');
+ this.isLoaded = false;
+ if (this.onCloseCallbacks.size) {
+ this.onCloseCallbacks.forEach(callback => {
+ callback();
+ });
+ }
+ // Cleanup keyboard shortcut bindings
+ for( const [, method] of Object.entries(this.keyboardShortcuts) ) {
+ document.removeEventListener('keydown', method);
+ }
+ return true;
},
/**
* Excavates a document fragment from the corresponding screen template
@@ -2493,6 +2539,17 @@ const managerScreen = {
}
],
onMainPanelCloseCallbacks: new Set(),
+ lastMainPanelSendParams: {},
+ keyboardShortcuts: {
+ 'reload': function(e) {
+ // R key (no meta)
+ if (!e.metaKey && (e.key === 'r' || e.key === 'R')) {
+ if (this.currentMainPath && !isActiveFormControl()) {
+ this.reloadMainPanel();
+ }
+ }
+ }
+ },
/**
* Runs all tasks required to load the screen
* @param {object} params - Params to use when loading
@@ -2571,7 +2628,7 @@ const managerScreen = {
this.listingGroup.prepend(item);
}
},
- (searchField) => {
+ searchField => {
if (searchField.value !== '') {
let params = {};
params[searchField.name] = searchField.value;
@@ -2590,7 +2647,9 @@ const managerScreen = {
document.body.dataset.layout = 'discrete';
} else if (layout === 'discrete') {
document.body.dataset.layout = 'open';
- this.listing.fillUpContents();
+ if (isCompact.matches) {
+ this.listing.fillUpContents();
+ }
}
});
}
@@ -2628,7 +2687,9 @@ const managerScreen = {
document.body.dataset.layout = 'discrete';
} else {
document.body.dataset.layout = 'open';
- this.listing.fillUpContents();
+ if (isCompact.matches) {
+ this.listing.fillUpContents();
+ }
}
// Project not found.
} else if (payload !== false && !payload.data) {
@@ -2711,17 +2772,23 @@ const managerScreen = {
* @param {string} path - File's path name
* @param {bool} setParams - Whether to set path name in location
*/
- loadIntoMainPanel(path, setParams = true) {
+ loadIntoMainPanel(path, setParams = true, sendParams = {}) {
if (
this.mainPanelAbortController
&& !this.mainPanelAbortController.signal.aborted
) {
this.mainPanelAbortController.abort();
}
- this.removeMainPanelMasterMessage();
- this.truncateMainPanel();
- this.mainPanel.removeAttribute('data-handler');
+ const loadCleanUp = () => {
+ this.removeMainPanelMasterMessage();
+ this.truncateMainPanel();
+ if (this.lastMainPanelSendParams) {
+ this.releaseParams(Object.keys(this.lastMainPanelSendParams));
+ }
+ this.mainPanel.removeAttribute('data-handler');
+ };
const waitingTimeout = setTimeout(() => {
+ loadCleanUp();
this.mainPanel.classList.add('wtng');
}, 150);
if (isCompact.matches) {
@@ -2744,9 +2811,13 @@ const managerScreen = {
this.loadedProjectData.pathname
);
}
+ for (const [key, val] of Object.entries(sendParams)) {
+ url.searchParams.set(key, val);
+ }
this.mainPanelAbortController = this.provideAbortController();
apiRequest(url, this.mainPanelAbortController).then(payload => {
if (payload !== false) {
+ loadCleanUp();
const data = payload.data;
const mainPanelToolbar = createElement('div', {
classes: ['tb'],
@@ -2788,12 +2859,16 @@ const managerScreen = {
data.meta.handlerName
);
if (setParams) {
- this.setParams({
+ const mainParams = {
main: path,
- });
+ };
+ this.setParams({...mainParams, ...sendParams});
+ this.lastMainPanelSendParams = sendParams;
}
this.currentMainPath = path;
} else {
+ this.currentMainPath = null;
+ this.truncateMainPanel();
this.putOnNoFileMessage();
this.releaseParams(['main'], 'replace');
}
@@ -3048,7 +3123,7 @@ const managerScreen = {
});
const currentButton = createElement('button', {
text: fileData.basename,
- title: "Reload file",
+ title: "Reload file (R)",
});
currentButton.addEventListener('click', () => {
this.reloadMainPanel();
@@ -3076,7 +3151,7 @@ const managerScreen = {
const reloadButton = createElement('button', {
classes: ['rld-btn'],
text: "Reload",
- title: "Reload file",
+ title: "Reload file (R)",
});
reloadButton.addEventListener('click', () => {
this.reloadMainPanel();
@@ -3103,6 +3178,26 @@ const managerScreen = {
});
menu.append(wordWrapButton);
}
+ if (fileData.category === 'demo' || fileData.category === 'unit') {
+ const toggleView = createElement('button', {
+ classes: ['tgl-view-btn'],
+ text: "Toggle view",
+ title: "Toggle view",
+ });
+ toggleView.addEventListener('click', () => {
+ if (!Object.hasOwn(stateObj, 'force_source')) {
+ this.loadIntoMainPanel(this.currentMainPath, true, {
+ 'force_source': '1',
+ });
+ } else {
+ this.loadIntoMainPanel(this.currentMainPath);
+ this.releaseParams([
+ 'force_source',
+ ]);
+ }
+ });
+ menu.append(toggleView);
+ }
menu.append(reloadButton, closeButton);
return menu;
},
@@ -3111,16 +3206,23 @@ const managerScreen = {
*/
reloadMainPanel() {
if (this.currentMainPath) {
- this.loadIntoMainPanel(this.currentMainPath);
+ this.loadIntoMainPanel(
+ this.currentMainPath,
+ true,
+ this.lastMainPanelSendParams
+ );
}
},
/**
* Closes main panel
*/
closeMainPanel() {
+ this.currentMainPath = null;
this.mainPanel.innerHTML = '';
this.putOnNoFileMessage();
- this.releaseParams(['main']);
+ this.releaseParams(
+ ['main', ...Object.keys(this.lastMainPanelSendParams)]
+ );
if (this.onMainPanelCloseCallbacks.size) {
this.onMainPanelCloseCallbacks.forEach(callback => {
callback();
@@ -3863,9 +3965,8 @@ const shortNotifications = {
function ShortNotification(text, timeout) {
const container = this.createElement();
container.innerText = text;
- this.container = shortNotifications.container.appendChild(
- container
- );
+ shortNotifications.container.prepend(container);
+ this.container = shortNotifications.container.firstElementChild;
this.timeoutHandlerId = setTimeout(() => {
this.close();
}, timeout);
diff --git a/src/web/app/index.html b/src/web/app/index.html
index 9510cbc..c8a3f2c 100644
--- a/src/web/app/index.html
+++ b/src/web/app/index.html
@@ -6,7 +6,7 @@
-
+
diff --git a/src/web/app/tpls/icons.html b/src/web/app/tpls/icons.html
index b0a71e8..7f826d2 100644
--- a/src/web/app/tpls/icons.html
+++ b/src/web/app/tpls/icons.html
@@ -72,9 +72,11 @@ CSS Icons
-
+
-
+
+
+
@@ -84,6 +86,10 @@ CSS Icons
+
+
+
+