Skip to content

Commit

Permalink
Add php 8 union function args and return
Browse files Browse the repository at this point in the history
  • Loading branch information
neild3r committed Aug 17, 2021
1 parent 3e0bb77 commit e6f49c2
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 57 deletions.
38 changes: 0 additions & 38 deletions src/block.ts
Expand Up @@ -220,44 +220,6 @@ export abstract class Block
return this.classHead;
}

/**
* Take the value and parse and try to infer its type
*
* @param {string} value
* @returns {string}
*/
public getTypeFromValue(value:string):string
{
let result:Array<string>;

// Check for bool
if (value.match(/^\s*(false|true)\s*$/i) !== null) {
return TypeUtil.instance.getFormattedTypeByName('bool');
}

// Check for int
if (value.match(/^\s*([\d-]+)\s*$/) !== null) {
return TypeUtil.instance.getFormattedTypeByName('int');
}

// Check for float
if (value.match(/^\s*([\d.-]+)\s*$/) !== null) {
return 'float';
}

// Check for string
if (value.match(/^\s*(["'])/) !== null) {
return 'string';
}

// Check for array
if (value.match(/^\s*(array\(|\[)/) !== null) {
return 'array';
}

return '[type]';
}

/**
* This is where we parse the code block into a Doc
* object which represents our snippet
Expand Down
24 changes: 11 additions & 13 deletions src/block/function.ts
Expand Up @@ -39,32 +39,30 @@ export default class FunctionBlock extends Block
}

for (let index = 0; index < args.length; index++) {
let arg = args[index];
let parts = arg.match(/^\s*(\?)?\s*([A-Za-z0-9_\\]+)?\s*\&?((?:[.]{3})?\$[A-Za-z0-9_]+)\s*\=?\s*(.*)\s*/m);
var type = '[type]';
let arg:string = args[index];
let parts:string[] = arg.match(/^\s*(\?)?\s*([A-Za-z0-9|_\\]+)?\s*\&?((?:[.]{3})?\$[A-Za-z0-9_]+)\s*\=?\s*(.*)\s*/m);
var type:string = '[type]';

if (parts[2] != null) {
parts[2] = TypeUtil.instance.getFullyQualifiedType(parts[2], head);
if (parts[2] != null) {
type = TypeUtil.instance.getResolvedTypeHints(parts[2], head);
}

if (parts[2] != null && parts[1] === '?') {
type = TypeUtil.instance.getFormattedTypeByName(parts[2])+'|null';
} else if (parts[2] != null) {
type = TypeUtil.instance.getFormattedTypeByName(parts[2]);
type += '|null';
} else if (parts[2] != null && parts[4] != null && parts[4] == "null") {
type += '|null';
} else if (parts[4] != null && parts[4] != "") {
type = TypeUtil.instance.getFormattedTypeByName(this.getTypeFromValue(parts[4]));
type = TypeUtil.instance.getFormattedTypeByName(TypeUtil.instance.getTypeFromValue(parts[4]));
}

doc.params.push(new Param(type, parts[3]));
}
}

let returnType:Array<string> = this.signature.match(/.*\)\s*\:\s*(\?)?\s*([a-zA-Z_0-9\\]+)\s*$/m);
let returnType:Array<string> = this.signature.match(/.*\)\s*\:\s*(\?)?\s*([a-zA-Z_|0-9\\]+)\s*$/m);

if (returnType != null) {
if (Config.instance.get('qualifyClassNames')) {
returnType[2] = TypeUtil.instance.getFullyQualifiedType(returnType[2], this.getClassHead());
}
returnType[2] = TypeUtil.instance.getResolvedTypeHints(returnType[2], this.getClassHead());

doc.return = (returnType[1] === '?')
? TypeUtil.instance.getFormattedTypeByName(returnType[2])+'|null'
Expand Down
4 changes: 2 additions & 2 deletions src/block/property.ts
Expand Up @@ -12,7 +12,7 @@ export default class Property extends Block
/**
* @inheritdoc
*/
protected pattern:RegExp = /^\s*(static)?\s*(protected|private|public)\s+(static)?\s*(\??\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\\]+)?\s*(\$[A-Za-z0-9_]+)\s*\=?\s*([^;]*)/m;
protected pattern:RegExp = /^\s*(static)?\s*(protected|private|public)\s+(static)?\s*(\??\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9|_\x7f-\xff\\]+)?\s*(\$[A-Za-z0-9_]+)\s*\=?\s*([^;]*)/m;

/**
* @inheritdoc
Expand Down Expand Up @@ -41,7 +41,7 @@ export default class Property extends Block

doc.var = varType;
} else if (params[6]) {
doc.var = this.getTypeFromValue(params[6]);
doc.var = TypeUtil.instance.getTypeFromValue(params[6]);
} else {
doc.var = '[type]';
}
Expand Down
57 changes: 57 additions & 0 deletions src/util/TypeUtil.ts
Expand Up @@ -21,6 +21,25 @@ export default class TypeUtil {
return this._instance || (this._instance = new this());
}

/**
* Resolve a type string that may contain union types
*
* @param {string} types
* @param {string} head
* @returns {string}
*/
public getResolvedTypeHints(types:string, head:string = null): string
{
let union:string[] = types.split("|");

for (let index = 0; index < union.length; index++) {
union[index] = this.getFullyQualifiedType(union[index], head);
union[index] = this.getFormattedTypeByName(union[index]);
}

return union.join("|");
}

/**
* Get the full qualified class namespace for a type
* we'll need to access the document
Expand Down Expand Up @@ -77,4 +96,42 @@ export default class TypeUtil {
}
}


/**
* Take the value and parse and try to infer its type
*
* @param {string} value
* @returns {string}
*/
public getTypeFromValue(value:string):string
{
let result:Array<string>;

// Check for bool
if (value.match(/^\s*(false|true)\s*$/i) !== null) {
return this.getFormattedTypeByName('bool');
}

// Check for int
if (value.match(/^\s*([\d-]+)\s*$/) !== null) {
return this.getFormattedTypeByName('int');
}

// Check for float
if (value.match(/^\s*([\d.-]+)\s*$/) !== null) {
return 'float';
}

// Check for string
if (value.match(/^\s*(["'])/) !== null) {
return 'string';
}

// Check for array
if (value.match(/^\s*(array\(|\[)/) !== null) {
return 'array';
}

return '[type]';
}
}
15 changes: 15 additions & 0 deletions test/fixtures/functions.php
Expand Up @@ -161,6 +161,21 @@ public function getPHP7ReturnNamespaceFull():App\Model\TypeHint
{
}

////=> php8-return-union-types
public function getPHP8ReturnUnionTypes():int|bool|\TypeHint|App\Model\TypeHint
{
}

////=> php8-return-union-types-with-short-name
public function getPHP8ReturnUnionTypesShortName():int|bool|\TypeHint|App\Model\TypeHint
{
}

////=> php8-param-union-types
public function getPHP8ParamUnionTypes(int|bool|\TypeHint|App\Model\TypeHint $arg, string|\Closure ...$args)
{
}

////=> function-reference
public function &someFunction()
{
Expand Down
39 changes: 39 additions & 0 deletions test/fixtures/functions.php.json
Expand Up @@ -361,6 +361,45 @@
"params": []
}
},
{
"key": "php8-return-union-types",
"name": "PHP8 return union types",
"result": {
"return": "integer|boolean|\\TypeHint|App\\Model\\TypeHint",
"params": []
}
},
{
"key": "php8-return-union-types-with-short-name",
"name": "PHP8 return union types with short-name",
"config": {
"useShortNames": true
},
"result": {
"return": "int|bool|\\TypeHint|App\\Model\\TypeHint",
"params": []
}
},
{
"key": "php8-param-union-types",
"name": "PHP8 param union types",
"config": {
"useShortNames": true
},
"result": {
"return": "void",
"params": [
{
"name": "$arg",
"type": "int|bool|\\TypeHint|App\\Model\\TypeHint"
},
{
"name": "...$args",
"type": "string|\\Closure"
}
]
}
},
{
"key": "function-reference",
"name": "Function with reference ampersand",
Expand Down
8 changes: 4 additions & 4 deletions test/properties.test.ts
@@ -1,7 +1,7 @@
import * as assert from 'assert';
import {TextEditor, TextDocument} from 'vscode';
import Helper from './helpers';
import Function from '../src/block/property';
import Property from '../src/block/property';
import {Doc, Param} from '../src/doc';

suite("Property tests", () => {
Expand All @@ -22,18 +22,18 @@ suite("Property tests", () => {

map.forEach(testData => {
test("Match Test: "+ testData.name, () => {
let func = new Function(testPositions[testData.key], editor);
let func = new Property(testPositions[testData.key], editor);
assert.equal(func.test(), true, test.name);
});

test("Parse Test: "+ testData.name, () => {
let func = new Function(testPositions[testData.key], editor);
let func = new Property(testPositions[testData.key], editor);
assert.ok(func.parse(), test.name);
});

test("Type Test: "+ testData.name, () => {
Helper.setConfig(testData.config);
let func = new Function(testPositions[testData.key], editor);
let func = new Property(testPositions[testData.key], editor);
let doc:Doc = func.parse();
assert.equal(doc.var, testData.var, test.name);
});
Expand Down

0 comments on commit e6f49c2

Please sign in to comment.