Skip to content

Commit c01ddaa

Browse files
authored
Merge pull request #22 from memory-agape/0.0.3.1
Support to inner class
2 parents e460118 + c4014cc commit c01ddaa

12 files changed

Lines changed: 146 additions & 24 deletions

File tree

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ We welcoming to contributions this project 💪
2121
## Not currently supported
2222
Sorry, I do not have enough time (T_T)
2323

24-
- Inner classes
2524
- Annotations
2625
- Extends other class
2726
- Implements

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "JVM emulator by PHP",
44
"type": "library",
55
"license": "MIT",
6-
"version": "0.0.3-dev",
6+
"version": "0.0.3.1-dev",
77
"authors": [
88
{
99
"name": "memory"

src/Core/JVM/Invoker/Invokable.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ public function call(string $name, ...$arguments)
6969
->getConstantPool()
7070
->getEntries();
7171

72+
if ($name === '<init>' && $this->javaClassInvoker->getJavaClass()->hasParentClass()) {
73+
array_unshift(
74+
$arguments,
75+
$this->javaClassInvoker->getJavaClass()->getParentClass()
76+
);
77+
}
78+
7279
// Find same method
7380
$convertedPassedArguments = Formatter::buildArgumentsSignature(
7481
array_map(
@@ -80,11 +87,12 @@ function ($argument) {
8087
);
8188

8289
$method = null;
90+
91+
// the special method
8392
foreach ($methodReferences as $methodReference) {
8493
$methodSignature = Formatter::buildArgumentsSignature(
8594
Formatter::parseSignature($constantPool[$methodReference->getDescriptorIndex()]->getString())['arguments']
8695
);
87-
8896
if ($methodSignature === $convertedPassedArguments) {
8997
$method = $methodReference;
9098
break;

src/Core/JavaClass.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use PHPJava\Core\JVM\ConstantPool;
99
use PHPJava\Core\JVM\Validations\MagicByte;
1010
use PHPJava\Exceptions\ValidatorException;
11+
use PHPJava\Kernel\Attributes\AttributeInterface;
12+
use PHPJava\Kernel\Attributes\InnerClassesAttribute;
1113
use PHPJava\Kernel\Maps\AccessFlag;
1214
use PHPJava\Kernel\Structures\_Utf8;
1315
use PHPJava\Utilities\Formatter;
@@ -62,6 +64,10 @@ class JavaClass
6264
*/
6365
private $invoker;
6466

67+
private $innerClasses = [];
68+
69+
private $parentClass;
70+
6571
/**
6672
* JavaClass constructor.
6773
* @param JavaClassReader $reader
@@ -94,6 +100,7 @@ public function __construct(JavaClassReader $reader)
94100
$this->thisClass = $reader->getBinaryReader()->readUnsignedShort();
95101

96102
$constantPoolEntries = $this->constantPool->getEntries();
103+
97104
$this->className = $constantPoolEntries[$constantPoolEntries[$this->thisClass]->getClassIndex()];
98105

99106
// read super class
@@ -127,14 +134,32 @@ public function __construct(JavaClassReader $reader)
127134
$this->constantPool
128135
);
129136

137+
foreach ($this->activeAttributes->getEntries() as $entry) {
138+
if ($entry->getAttributeData() instanceof InnerClassesAttribute) {
139+
$this->innerClasses = array_merge(
140+
$this->innerClasses,
141+
$entry->getAttributeData()->getClasses()
142+
);
143+
}
144+
}
145+
130146
$this->invoker = new JavaClassInvoker($this);
131147
}
132148

133-
public function getClassName(): string
149+
public function getClassName(bool $shortName = false): string
134150
{
151+
if ($shortName === true) {
152+
$split = explode('$', $this->className->getString());
153+
return $split[count($split) - 1];
154+
}
135155
return $this->className->getString();
136156
}
137157

158+
public function getInnerClasses(): array
159+
{
160+
return $this->innerClasses;
161+
}
162+
138163
public function getFields(): array
139164
{
140165
return $this->activeFields->getEntries();
@@ -156,6 +181,22 @@ public function appendDebug($log)
156181
return $this;
157182
}
158183

184+
public function hasParentClass(): bool
185+
{
186+
return isset($this->parentClass);
187+
}
188+
189+
public function setParentClass(JavaClass $class): self
190+
{
191+
$this->parentClass = $class;
192+
return $this;
193+
}
194+
195+
public function getParentClass(): JavaClass
196+
{
197+
return $this->parentClass;
198+
}
199+
159200
public function debug(): void
160201
{
161202
$cpInfo = $this->getConstantPool()->getEntries();

src/Core/JavaClassInvoker.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,18 @@ public function __construct(JavaClass $javaClass)
9393
}
9494

9595
/**
96+
* @param array $arguments
9697
* @return JavaClassInvoker
9798
*/
98-
public function construct(): self
99+
public function construct(...$arguments): self
99100
{
100101
$this->dynamicAccessor = new DynamicAccessor(
101102
$this,
102103
$this->dynamicMethods
103104
);
104105

105106
if (isset($this->dynamicMethods['<init>'])) {
106-
$this->getDynamic()->getMethods()->call('<init>');
107+
$this->getDynamic()->getMethods()->call('<init>', ...$arguments);
107108
}
108109

109110
return $this;

src/Kernel/Attributes/InnerClassesAttribute.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace PHPJava\Kernel\Attributes;
33

44
use PHPJava\Exceptions\NotImplementedException;
5+
use PHPJava\Kernel\Structures\_Classes;
56
use PHPJava\Utilities\BinaryTool;
67

78
final class InnerClassesAttribute implements AttributeInterface
@@ -10,20 +11,21 @@ final class InnerClassesAttribute implements AttributeInterface
1011
use \PHPJava\Kernel\Core\ConstantPool;
1112

1213
private $numberOfClasses = 0;
13-
private $classes = array();
14+
private $classes = [];
15+
1416
public function execute(): void
1517
{
1618
$this->numberOfClasses = $this->readUnsignedShort();
1719
for ($i = 0; $i < $this->numberOfClasses; $i++) {
18-
$thises[$i] = new JavaStructureClasses($this);
19-
$thises[$i]->setInnerClassInfoIndex($this->readUnsignedShort());
20-
$thises[$i]->setOuterClassInfoIndex($this->readUnsignedShort());
21-
$thises[$i]->setInnerNameIndex($this->readUnsignedShort());
22-
$thises[$i]->setInnerClassAccessFlag($this->readUnsignedShort());
20+
$this->classes[$i] = new _Classes($this->reader);
21+
$this->classes[$i]->setInnerClassInfoIndex($this->readUnsignedShort());
22+
$this->classes[$i]->setOuterClassInfoIndex($this->readUnsignedShort());
23+
$this->classes[$i]->setInnerNameIndex($this->readUnsignedShort());
24+
$this->classes[$i]->setInnerClassAccessFlag($this->readUnsignedShort());
2325
}
2426
}
25-
public function getClasses()
27+
public function getClasses(): array
2628
{
27-
return $thises;
29+
return $this->classes;
2830
}
2931
}

src/Kernel/Mnemonics/_invokespecial.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function execute(): void
3030
krsort($arguments);
3131

3232
$methodName = $cpInfo[$nameAndTypeIndex->getNameIndex()]->getString();
33+
3334
if ($this->javaClassInvoker->isInvoked($methodName, $signature)) {
3435
return;
3536
}
@@ -38,7 +39,18 @@ public function execute(): void
3839
->addToSpecialInvokedList($methodName, $signature);
3940

4041
if ($invokerClass instanceof JavaClass) {
41-
$result = $invokerClass->getInvoker()->getDynamic()->getMethods()
42+
if ($invokerClass->getInvoker()->isInvoked($methodName, $signature)) {
43+
return;
44+
}
45+
46+
$invokerClass
47+
->getInvoker()
48+
->addToSpecialInvokedList($methodName, $signature);
49+
50+
$result = $invokerClass
51+
->getInvoker()
52+
->getDynamic()
53+
->getMethods()
4254
->call(
4355
$methodName,
4456
...$arguments

src/Kernel/Mnemonics/_new.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,13 @@ public function execute(): void
2121
return;
2222
}
2323

24-
[$resourceType, $classObject] = ClassResolver::resolve($className);
24+
[$resourceType, $classObject] = ClassResolver::resolve($className, $this->javaClass);
2525
if ($resourceType === ClassResolver::RESOLVED_TYPE_CLASS) {
2626
/**
2727
* @var \PHPJava\Core\JavaClass $classObject
2828
*/
29-
$this->pushStack(
30-
$classObject
31-
->getInvoker()
32-
->construct()
33-
->getJavaClass()
34-
);
29+
30+
$this->pushStack($classObject->getInvoker()->construct()->getJavaClass());
3531
return;
3632
}
3733
$this->pushStack(new $classObject());

src/Utilities/ClassResolver.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ClassResolver
2121
private static $resolves = [];
2222
private static $resolvedPaths = [];
2323

24-
public static function resolve($javaPath): array
24+
public static function resolve(string $javaPath, JavaClass $class = null): array
2525
{
2626
$namespaces = explode('.', str_replace('/', '.', $javaPath));
2727
$buildClassPath = [];
@@ -39,9 +39,13 @@ public static function resolve($javaPath): array
3939
return static::$resolvedPaths[$key];
4040
}
4141
if (is_file($path)) {
42+
$initiatedClass = new JavaClass(new JavaClassReader($path));
43+
if (strpos($relativePath, '$') !== false && $class !== null) {
44+
$initiatedClass->setParentClass($class);
45+
}
4246
return $resolvedPaths[] = [
4347
static::RESOLVED_TYPE_CLASS,
44-
new JavaClass(new JavaClassReader($path)),
48+
$initiatedClass,
4549
];
4650
}
4751
break;

src/Utilities/TypeResolver.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace PHPJava\Utilities;
33

4+
use PHPJava\Core\JavaClass;
45
use PHPJava\Exceptions\TypeException;
56

67
class TypeResolver
@@ -76,6 +77,16 @@ public static function convertPHPtoJava($arguments, $defaultJavaArgumentType = '
7677
$firstParameter['deep_array'] += $deepArray;
7778
return $firstParameter;
7879
}
80+
if ($phpType === 'object') {
81+
if ($arguments instanceof JavaClass) {
82+
return [
83+
'type' => 'class',
84+
'class_name' => $arguments->getClassName(false),
85+
'deep_array' => $deepArray,
86+
];
87+
}
88+
throw new TypeException(get_class($arguments) . ' does not supported to convert to Java\'s argument.');
89+
}
7990
$resolveType = static::SIGNATURE_MAP[static::PHP_TYPE_MAP[$phpType][0]] ?? null;
8091
if ($resolveType === 'class') {
8192
return [

0 commit comments

Comments
 (0)