Skip to content

Commit

Permalink
Merge 0546043 into 8e4162e
Browse files Browse the repository at this point in the history
  • Loading branch information
neild3r committed Mar 25, 2018
2 parents 8e4162e + 0546043 commit acb4139
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 114 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This extension contributes the following settings:
* `php-docblocker.returnGap`: set to `true` to add a gap between the param and return tags
* `php-docblocker.extra`: an array of extra tags to add to each DocBlock (These can include tabstops and snippet variables)
* `php-docblocker.useShortNames`: Whether we should use short type names. e.g. bool or boolean
* `php-docblocker.qualifyClassNames`: When adding type hints for class names search namespace use statements and qualify the class
* `php-docblocker.author`: An object containing your default author tag settings

## Supported DocBlock tags
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
"default": false,
"description": "Wether you want to use integer instead of int and boolean instead of bool."
},
"php-docblocker.qualifyClassNames": {
"type": "boolean",
"default": false,
"description": "Fully qualifies any data types used in param and returns by reading the namespaces."
},
"php-docblocker.author": {
"type": "object",
"default": {
Expand Down
26 changes: 26 additions & 0 deletions src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ export abstract class Block
*/
protected signatureEnd:RegExp = /[\{;]/;

/**
* Class heading
*
* @type {string}
*/
protected classHead:string;

/**
* Creates an instance of Block.
*
Expand Down Expand Up @@ -153,6 +160,25 @@ export abstract class Block
return context.substr(0, endPos);
}

/**
* Get the header for the class
*
* @returns {string}
*/
public getClassHead():string
{
if (this.classHead === undefined) {
let text = this.editor.document.getText();
let regex = /\s*(abstract|final)?\s*(class|trait|interface)/gm;
let match = regex.exec(text);
let end = this.editor.document.positionAt(match.index);
let range = new Range(new Position(0, 0), end);
this.classHead = this.editor.document.getText(range);
}

return this.classHead;
}

/**
* Take the value and parse and try to infer its type
*
Expand Down
18 changes: 17 additions & 1 deletion src/block/function.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Block } from "../block";
import { Doc, Param } from "../doc";
import TypeUtil from "../util/TypeUtil";
import { Range, Position } from "vscode";
import Config from "../util/config";

/**
* Represents a function code block
Expand All @@ -11,7 +13,6 @@ import TypeUtil from "../util/TypeUtil";
*/
export default class FunctionBlock extends Block
{

/**
* @inheritdoc
*/
Expand All @@ -26,14 +27,25 @@ export default class FunctionBlock extends Block

let doc = new Doc('Undocumented function');
let argString = this.getEnclosed(params[6], "(", ")");
let head:string;


if (argString != "") {
let args = argString.split(',');

if (Config.instance.get('qualifyClassNames')) {
head = this.getClassHead();
}

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]';

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

if (parts[2] != null && parts[1] === '?') {
type = TypeUtil.instance.getFormattedTypeByName(parts[2])+'|null';
} else if (parts[2] != null) {
Expand All @@ -49,6 +61,10 @@ export default class FunctionBlock extends Block
let returnType:Array<string> = this.signature.match(/.*\)\s*\:\s*(\?)?\s*([a-zA-Z\\]+)\s*$/m);

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

doc.return = (returnType[1] === '?')
? TypeUtil.instance.getFormattedTypeByName(returnType[2])+'|null'
: TypeUtil.instance.getFormattedTypeByName(returnType[2]);
Expand Down
35 changes: 3 additions & 32 deletions src/completions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import {workspace, TextDocument, Position, CancellationToken, ProviderResult, CompletionItem, CompletionItemProvider, Range, SnippetString, CompletionItemKind, window} from "vscode";
import Documenter from "./documenter";
import Config from "./util/config";

/**
* Completions provider that can be registered to the language
*/
export default class Completions implements CompletionItemProvider
{
/**
* A config which will modify the result of the docblock
*
* @type {{}}
*/
protected config:{};

/**
* List of tags and snippets that are filled in docblocks
*
Expand Down Expand Up @@ -160,29 +154,6 @@ export default class Completions implements CompletionItemProvider
*/
protected formatted = false;

/**
* Get the config from either vs code or the manually set one
*
* @returns {*}
*/
public getConfig():any
{
if (this.config == null) {
this.setConfig(workspace.getConfiguration().get('php-docblocker'));
}
return this.config;
}

/**
* Set the config object
*
* @param {*} config
*/
public setConfig(config:any):void
{
this.config = config;
}

/**
* Implemented function to find and return completions either from
* the tag list or initiate a complex completion
Expand Down Expand Up @@ -240,8 +211,8 @@ export default class Completions implements CompletionItemProvider
if (!this.formatted) {
this.tags.forEach((tag, index) => {
if (tag.tag == '@author') {
tag.snippet = tag.snippet.replace("{{name}}", this.getConfig().author.name);
tag.snippet = tag.snippet.replace("{{email}}", this.getConfig().author.email);
tag.snippet = tag.snippet.replace("{{name}}", Config.instance.get('author').name);
tag.snippet = tag.snippet.replace("{{email}}", Config.instance.get('author').email);
this.tags[index] = tag;
}
});
Expand Down
37 changes: 4 additions & 33 deletions src/doc.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {workspace, SnippetString, WorkspaceConfiguration} from 'vscode';
import Config from './util/config';

/**
* Represents a comment block.
Expand Down Expand Up @@ -36,13 +37,6 @@ export class Doc
*/
public message:string;

/**
* A config which will modify the result of the docblock
*
* @type {{}}
*/
protected config:{};

/**
* Creates an instance of Doc.
*
Expand Down Expand Up @@ -76,29 +70,6 @@ export class Doc
}
}

/**
* Get the config from either vs code or the manually set one
*
* @returns {*}
*/
public getConfig():any
{
if (this.config == null) {
this.config = workspace.getConfiguration().get('php-docblocker');
}
return this.config;
}

/**
* Set the config object
*
* @param {*} config
*/
public setConfig(config:any):void
{
this.config = config;
}

/**
* Build all the set values into a SnippetString ready for use
*
Expand All @@ -108,9 +79,9 @@ export class Doc
public build(isEmpty:boolean = false):SnippetString
{
let snippet = new SnippetString();
let extra = this.getConfig().extra;
let gap = !this.getConfig().gap;
let returnGap = this.getConfig().returnGap;
let extra = Config.instance.get('extra');
let gap = !Config.instance.get('gap');
let returnGap = Config.instance.get('returnGap');

if (isEmpty) {
gap = true;
Expand Down
51 changes: 28 additions & 23 deletions src/util/TypeUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { workspace } from "vscode";
import { workspace, TextEditor, Range, Position, TextDocument } from "vscode";
import Config from "./config";

/**
* Provides helper function to types
Expand All @@ -11,13 +12,6 @@ export default class TypeUtil {
*/
private static _instance: TypeUtil;

/**
* Holds wether we use short names or not
*
* @type {bool|null}
*/
private _useShortNames: any;

/**
* Returns the instance for this util
*
Expand All @@ -28,24 +22,35 @@ export default class TypeUtil {
}

/**
* Overwrites the value
* Get the full qualified class namespace for a type
* we'll need to access the document
*
* @param {boolean} value
* @param {string} type
* @param {string} head
* @returns {string}
*/
public set useShortNames(value:boolean) {
this._useShortNames = value;
}
public getFullyQualifiedType(type:string, head:string):string
{
if (!Config.instance.get('qualifyClassNames')) {
return type;
}

/**
* Returns wether we use long names or not.
*/
public get useShortNames() {
if (this._useShortNames == null) {
let config: any = workspace.getConfiguration().get('php-docblocker');
this._useShortNames = config.useShortNames || false;
let useEx = new RegExp("use\\s+([^ ]*?)((?:\\s+as\\s+))?("+type+");", 'gm');
let full = useEx.exec(head);

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

if (full[2] != null) {
return full[1];
}

return full[1] + type;
}

return this._useShortNames;
return type;
}

/**
Expand All @@ -57,13 +62,13 @@ export default class TypeUtil {
switch (name) {
case 'bool':
case 'boolean':
if (!this.useShortNames) {
if (!Config.instance.get('useShortNames')) {
return 'boolean';
}
return 'bool';
case 'int':
case 'integer':
if (!this.useShortNames) {
if (!Config.instance.get('useShortNames')) {
return 'integer';
}
return 'int';
Expand Down
Loading

0 comments on commit acb4139

Please sign in to comment.