Skip to content

Commit

Permalink
Merge 10c579a into cb1e8e3
Browse files Browse the repository at this point in the history
  • Loading branch information
tianyiw2013 committed Dec 10, 2021
2 parents cb1e8e3 + 10c579a commit fedd3d9
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
All notable changes to the "php-docblocker" extension will be documented in this file.

## [Unreleased]
- Fixed fully qualifies class namespace detection can be incorrect with _ [#214](https://github.com/neild3r/vscode-php-docblocker/issues/214)
- Supported fully qualifies class namespace use with bracket `use some\namespace\{ ClassA, ClassB, ... }`
- Supported fully qualifies class namespace use with comma `use some\namespace\ClassA, some\namespace\ClassB, ...`

## [2.6.1] - 2021-10-12
- Fix double start delimeter when vscode setting `editor.autoClosingBrackets` is set to `never`
Expand Down
Empty file added coverage/lcov.info
Empty file.
51 changes: 42 additions & 9 deletions src/util/TypeUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { workspace, TextEditor, Range, Position, TextDocument } from "vscode";
import { TextEditor, Range, Position, TextDocument } from "vscode";
import Config from "./config";

/**
Expand Down Expand Up @@ -50,23 +50,56 @@ export default class TypeUtil {
*/
public getFullyQualifiedType(type:string, head:string):string
{
if (!head) {
return type;
}
if (!Config.instance.get('qualifyClassNames')) {
return type;
}

let useEx = new RegExp("use\\s+([^ ]*?)((?:\\s+as\\s+))?("+type+");", 'gm');
let full = useEx.exec(head);
let useEx = /[\s;]?use\s+(?:(const|function)\s*)?([\s\S]*?)\s*;/gmi;
let exec: RegExpExecArray;
while (exec = useEx.exec(head)) {
let is_const_or_func = exec[1];
let value = exec[2];

if (full != null && full[3] == type) {
if (full[1].charAt(0) != '\\') {
full[1] = '\\' + full[1];
if (is_const_or_func) {
continue;
}

if (full[2] != null) {
return full[1];
let classes: string[];
let prefix: string;
let with_bracket = value.indexOf('{') !== -1;
if (with_bracket) {
value += '}'; // fault-tolerant
let bracket_begin = value.indexOf('{');
let bracket_end = value.indexOf('}');
prefix = value.substring(0, bracket_begin).trim();
classes = value.substring(bracket_begin + 1, bracket_end).split(',');
} else {
prefix = '';
classes = value.split(',');
}

return full[1] + type;
for (let index = 0; index < classes.length; index++) {
value = classes[index].trim();
if (!value) {
continue;
}
value = prefix + value;
let [clazz, alias] = value.split(/\s+as\s+/gmi, 2);
if (!alias && clazz.endsWith('\\' + type)) {
// aa\bb
} else if (alias === type) {
// aa\bb as cc
} else {
continue;
}
if (clazz.charAt(0) != '\\') {
clazz = '\\' + clazz;
}
return clazz;
}
}

return type;
Expand Down
42 changes: 42 additions & 0 deletions test/TypeUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,48 @@ suite("TypeUtil tests: ", () => {
assert.equal(type.getFullyQualifiedType('BaseExample', head), '\\App\\Test\\Model\\Example');
});

test("Fully qualify typehint from namespace use with _", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('ExampleInterface', head), '\\App\\Example\\ExampleInterface');
});

test("Fully qualify typehint from namespace use with bracket", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('ClassA', head), '\\some\\namespace\\ClassA');
});

test("Fully qualify typehint from namespace use with bracket+alias", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('ClassB_alias', head), '\\some\\namespace\\ClassB');
});

test("Fully qualify typehint from namespace use with comma", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('ClassD', head), '\\some\\namespace\\ClassD');
});

test("Fully qualify typehint from namespace use with comma+alias", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('ClassE_alias', head), '\\some\\namespace\\ClassE');
});

test("Fully qualify typehint from namespace use const", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('myconst', head), 'myconst');
});

test("Fully qualify typehint from namespace use function", () => {
let type = new TypeUtil;
Helper.setConfig({qualifyClassNames: true});
assert.equal(type.getFullyQualifiedType('myfunction', head), 'myfunction');
});

test("With default settings the integer type formatted is integer", () => {
let type = new TypeUtil;
assert.equal(type.getFormattedTypeByName('int'), 'integer');
Expand Down
13 changes: 13 additions & 0 deletions test/fixtures/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;

use Example_ExampleInterface;
use App\Example\ExampleInterface;

use some\namespace\{
ClassA,
ClassB as ClassB_alias,
};
use some\namespace\ClassD,
some\namespace\ClassE as ClassE_alias;

use const some\namespace\myconst;
use function some\namespace\myfunction;

/**
* Example class here
*/
Expand Down

0 comments on commit fedd3d9

Please sign in to comment.