Skip to content

Commit 90082c1

Browse files
committed
PhpNamespace: addUse() & simplifyName() is case-insensitive
1 parent 5a39bcf commit 90082c1

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

src/PhpGenerator/PhpNamespace.php

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
use Nette;
1313
use Nette\InvalidStateException;
14-
use Nette\Utils\Strings;
1514

1615

1716
/**
@@ -107,22 +106,23 @@ public function addUse(string $name, string $alias = null, string $of = self::NA
107106
}
108107

109108
$name = ltrim($name, '\\');
110-
$aliases = $this->aliases[$of];
109+
$aliases = array_change_key_case($this->aliases[$of]);
111110
$used = [self::NAME_NORMAL => $this->classes, self::NAME_FUNCTION => $this->functions, self::NAME_CONSTANT => []][$of];
112111

113112
if ($alias === null) {
114113
$base = Helpers::extractShortName($name);
115114
$counter = null;
116115
do {
117116
$alias = $base . $counter;
117+
$lower = strtolower($alias);
118118
$counter++;
119-
} while ((isset($aliases[$alias]) && $aliases[$alias] !== $name) || isset($used[strtolower($alias)]));
119+
} while ((isset($aliases[$lower]) && strcasecmp($aliases[$lower], $name) !== 0) || isset($used[$lower]));
120120

121121
} else {
122122
$lower = strtolower($alias);
123-
if (isset($aliases[$alias]) && $aliases[$alias] !== $name) {
123+
if (isset($aliases[$lower]) && strcasecmp($aliases[$lower], $name) !== 0) {
124124
throw new InvalidStateException(
125-
"Alias '$alias' used already for '{$aliases[$alias]}', cannot use for '$name'."
125+
"Alias '$alias' used already for '{$aliases[$lower]}', cannot use for '$name'."
126126
);
127127
} elseif (isset($used[$lower])) {
128128
throw new Nette\InvalidStateException("Name '$alias' used already for '$this->name\\{$used[$lower]->getName()}'.");
@@ -185,13 +185,12 @@ public function simplifyName(string $name, string $of = self::NAME_NORMAL): stri
185185
return $this->simplifyName(Helpers::extractNamespace($name) . '\\') . Helpers::extractShortName($name);
186186
}
187187

188-
$lower = strtolower($name);
189-
$res = Strings::startsWith($lower, strtolower($this->name) . '\\')
188+
$res = self::startsWith($name, $this->name . '\\')
190189
? substr($name, strlen($this->name) + 1)
191190
: null;
192191

193192
foreach ($this->aliases[$of] as $alias => $original) {
194-
if (Strings::startsWith($lower . '\\', strtolower($original) . '\\')) {
193+
if (self::startsWith($name . '\\', $original . '\\')) {
195194
$short = $alias . substr($name, strlen($original));
196195
if (!isset($res) || strlen($res) > strlen($short)) {
197196
$res = $short;
@@ -209,10 +208,12 @@ public function add(ClassType $class): self
209208
$name = $class->getName();
210209
if ($name === null) {
211210
throw new Nette\InvalidArgumentException('Class does not have a name.');
212-
} elseif ($orig = $this->aliases[self::NAME_NORMAL][$name] ?? null) {
211+
}
212+
$lower = strtolower($name);
213+
if ($orig = array_change_key_case($this->aliases[self::NAME_NORMAL])[$lower] ?? null) {
213214
throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig.");
214215
}
215-
$this->classes[strtolower($name)] = $class;
216+
$this->classes[$lower] = $class;
216217
return $this;
217218
}
218219

@@ -245,7 +246,7 @@ public function addEnum(string $name): ClassType
245246
public function addFunction(string $name): GlobalFunction
246247
{
247248
$lower = strtolower($name);
248-
if ($orig = $this->aliases[self::NAME_FUNCTION][$name] ?? null) {
249+
if ($orig = array_change_key_case($this->aliases[self::NAME_FUNCTION])[$lower] ?? null) {
249250
throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig.");
250251
}
251252
return $this->functions[$lower] = new GlobalFunction($name);
@@ -274,6 +275,12 @@ public function getFunctions(): array
274275
}
275276

276277

278+
private static function startsWith(string $a, string $b): bool
279+
{
280+
return strncasecmp($a, $b, strlen($b)) === 0;
281+
}
282+
283+
277284
public function __toString(): string
278285
{
279286
try {

tests/PhpGenerator/PhpNamespace.aliases.phpt

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Assert::same('foo\A', $namespace->simplifyName('foo\A'));
1818
$namespace->addUse('Bar\C');
1919

2020
Assert::same('Bar', $namespace->simplifyName('Bar'));
21-
Assert::same('C', $namespace->simplifyName('Bar\C'));
21+
Assert::same('C', $namespace->simplifyName('bar\C'));
2222
Assert::same('C\D', $namespace->simplifyName('Bar\C\D'));
2323

2424
foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self', 'parent', ''] as $type) {
@@ -27,9 +27,9 @@ foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self
2727

2828
$namespace->addUseFunction('Foo\a');
2929

30-
Assert::same('Bar\c', $namespace->simplifyName('Bar\c', $namespace::NAME_FUNCTION));
31-
Assert::same('a', $namespace->simplifyName('Foo\A', $namespace::NAME_FUNCTION));
32-
Assert::same('Foo\a\b', $namespace->simplifyName('Foo\a\b', $namespace::NAME_FUNCTION));
30+
Assert::same('bar\c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION));
31+
Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NAME_FUNCTION));
32+
Assert::same('foo\a\b', $namespace->simplifyName('foo\a\b', $namespace::NAME_FUNCTION));
3333

3434
foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self', 'parent', ''] as $type) {
3535
Assert::same($type, $namespace->simplifyName($type, $namespace::NAME_FUNCTION));
@@ -38,13 +38,13 @@ foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self
3838
$namespace->addUseFunction('Bar\c');
3939

4040
Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NAME_FUNCTION));
41-
Assert::same('c', $namespace->simplifyName('Bar\c', $namespace::NAME_FUNCTION));
41+
Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION));
4242
Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_FUNCTION));
4343

4444
$namespace->addUseConstant('Bar\c');
4545

4646
Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NAME_CONSTANT));
47-
Assert::same('c', $namespace->simplifyName('Bar\c', $namespace::NAME_CONSTANT));
47+
Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_CONSTANT));
4848
Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_CONSTANT));
4949

5050

@@ -78,16 +78,16 @@ Assert::same('žluťoučký', $namespace->simplifyType('foo\žluťoučký'));
7878

7979
$namespace->addUseFunction('Foo\a');
8080

81-
Assert::same('\Bar\c', $namespace->simplifyName('Bar\c', $namespace::NAME_FUNCTION));
82-
Assert::same('a', $namespace->simplifyName('Foo\a', $namespace::NAME_FUNCTION));
83-
Assert::same('C\b', $namespace->simplifyName('Foo\C\b', $namespace::NAME_FUNCTION));
84-
Assert::same('a\b', $namespace->simplifyName('Foo\a\b', $namespace::NAME_FUNCTION));
81+
Assert::same('\bar\c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION));
82+
Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NAME_FUNCTION));
83+
Assert::same('C\b', $namespace->simplifyName('foo\C\b', $namespace::NAME_FUNCTION));
84+
Assert::same('a\b', $namespace->simplifyName('foo\a\b', $namespace::NAME_FUNCTION));
8585

8686
$namespace->addUseFunction('Bar\c');
8787

8888
Assert::same('\Bar', $namespace->simplifyName('Bar', $namespace::NAME_FUNCTION));
89-
Assert::same('c', $namespace->simplifyName('Bar\c', $namespace::NAME_FUNCTION));
90-
Assert::same('C\d', $namespace->simplifyName('Bar\c\d', $namespace::NAME_FUNCTION));
89+
Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION));
90+
Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_FUNCTION));
9191

9292

9393
// duplicity
@@ -98,21 +98,37 @@ Assert::exception(function () use ($namespace) {
9898
$namespace->addTrait('C');
9999
}, Nette\InvalidStateException::class, "Name 'C' used already as alias for Bar\\C.");
100100

101+
Assert::exception(function () use ($namespace) {
102+
$namespace->addTrait('c');
103+
}, Nette\InvalidStateException::class, "Name 'c' used already as alias for Bar\\C.");
104+
101105
$namespace->addClass('B');
102106
Assert::exception(function () use ($namespace) {
103107
$namespace->addUse('Lorem\B', 'B');
104108
}, Nette\InvalidStateException::class, "Name 'B' used already for 'Foo\\B'.");
105109

110+
Assert::exception(function () use ($namespace) {
111+
$namespace->addUse('lorem\b', 'b');
112+
}, Nette\InvalidStateException::class, "Name 'b' used already for 'Foo\\B'.");
113+
106114
$namespace->addUseFunction('Bar\f1');
107115
Assert::exception(function () use ($namespace) {
108116
$namespace->addFunction('f1');
109117
}, Nette\InvalidStateException::class, "Name 'f1' used already as alias for Bar\\f1.");
110118

119+
Assert::exception(function () use ($namespace) {
120+
$namespace->addFunction('F1');
121+
}, Nette\InvalidStateException::class, "Name 'F1' used already as alias for Bar\\f1.");
122+
111123
$namespace->addFunction('f2');
112124
Assert::exception(function () use ($namespace) {
113125
$namespace->addUseFunction('Bar\f2', 'f2');
114126
}, Nette\InvalidStateException::class, "Name 'f2' used already for 'Foo\\f2'.");
115127

128+
Assert::exception(function () use ($namespace) {
129+
$namespace->addUseFunction('Bar\f2', 'F2');
130+
}, Nette\InvalidStateException::class, "Name 'F2' used already for 'Foo\\f2'.");
131+
116132
Assert::same(['C' => 'Bar\C'], $namespace->getUses());
117133
Assert::same(['f1' => 'Bar\f1'], $namespace->getUses($namespace::NAME_FUNCTION));
118134

0 commit comments

Comments
 (0)