Skip to content

Commit

Permalink
Rebase and fix code changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
zobo committed Jan 21, 2022
1 parent 98bd782 commit 95e0764
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Options specific to CLI debugging:
- Stack traces, scope variables, superglobals, user defined constants
- Arrays & objects (including classname, private and static properties)
- Debug console
- Autocompletion in debug console for variables, array indexes, object properties (even nested)
- Autocompletion in debug console for variables, array indexes, object properties (even nested)
- Watches
- Run as CLI
- Run without debugging
Expand Down
105 changes: 62 additions & 43 deletions src/phpDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class PhpDebugSession extends vscode.DebugSession {
supportsFunctionBreakpoints: true,
supportsLogPoints: true,
supportsHitConditionalBreakpoints: true,
supportsCompletionsRequest: true,
exceptionBreakpointFilters: [
{
filter: 'Notice',
Expand Down Expand Up @@ -993,106 +994,124 @@ class PhpDebugSession extends vscode.DebugSession {
this.sendResponse(response)
}

protected async completionsRequest(response: VSCodeDebugProtocol.CompletionsResponse, args: VSCodeDebugProtocol.CompletionsArguments) {
protected async completionsRequest(
response: VSCodeDebugProtocol.CompletionsResponse,
args: VSCodeDebugProtocol.CompletionsArguments
) {
try {
if (!args.frameId) {
throw new Error('No stack frame given');
throw new Error('No stack frame given')
}
const lineIndex: number = args.line ? args.line - 1 : 0;
const lines: string[] = args.text.split('\n');
const lineIndex: number = args.line ? args.line - 1 : 0
const lines: string[] = args.text.split('\n')
/** The text before the cursor */
const typed: string = [...lines.slice(0, Math.max(lineIndex - 1, 0)), lines[lineIndex].substring(0, args.column)].join('\n');
let i = typed.length;
let containerName: string;
let operator: string | undefined;
let query: string;
const typed: string = [
...lines.slice(0, Math.max(lineIndex - 1, 0)),
lines[lineIndex].substring(0, args.column),
].join('\n')
let i = typed.length
let containerName: string
let operator: string | undefined
let query: string
while (true) {
const substr = typed.substring(0, i);
const substr = typed.substring(0, i)
if (/\[$/.test(substr)) {
// Numeric array index
operator = '[';
operator = '['
} else if (/\['$/.test(substr)) {
// String array index
operator = `['`;
operator = `['`
} else if (/->$/.test(substr)) {
operator = '->';
operator = '->'
} else if (i > 0) {
i--;
continue;
i--
continue
}
query = typed.substr(i).toLowerCase();
containerName = typed.substring(0, operator ? i - operator.length : i);
break;
query = typed.substr(i).toLowerCase()
containerName = typed.substring(0, operator ? i - operator.length : i)
break
}
const frame = this._stackFrames.get(args.frameId);
const contexts = await frame.getContexts();
const targets: VSCodeDebugProtocol.CompletionItem[] = [];
const frame = this._stackFrames.get(args.frameId)!
const contexts = await frame.getContexts()
const targets: VSCodeDebugProtocol.CompletionItem[] = []
if (!containerName || !operator) {
const responses = await Promise.all(contexts.map(context => context.getProperties()));
const responses = await Promise.all(contexts.map(context => context.getProperties()))
for (const properties of responses) {
for (const property of properties) {
if (property.name.toLowerCase().startsWith(query)) {
const text = property.name[0] === '$' ? property.name.substr(1) : property.name;
targets.push({label: property.name, text, type: 'variable', start: i, length: property.name.length});
const text = property.name[0] === '$' ? property.name.substr(1) : property.name
targets.push({
label: property.name,
text,
type: 'variable',
//start: i,
length: property.name.length,
})
}
}
}
} else {
// Search all contexts
for (const context of contexts) {
let response: xdebug.PropertyGetResponse | undefined;
let response: xdebug.PropertyGetResponse | undefined
try {
response = await frame.connection.sendPropertyGetCommand({context, fullName: containerName});
response = await frame.connection.sendPropertyGetCommand({ context, fullName: containerName })
} catch (err) {
// ignore
}
if (response) {
for (const property of response.children) {
if (property.name.toLowerCase().startsWith(query)) {
let type: VSCodeDebugProtocol.CompletionItemType | undefined;
let text: string = property.name;
let type: VSCodeDebugProtocol.CompletionItemType | undefined
let text: string = property.name
if (operator === '->') {
// Object
type = 'property';
type = 'property'
} else if (operator[0] === '[') {
// Array
if (parseInt(property.name) + '' === property.name) {
// Numeric index
if (operator[1] === `'`) {
continue;
continue
}
type = 'value';
text += ']';
type = 'value'
text += ']'
} else {
// String index
if (operator[1] !== `'`) {
if (query) {
continue;
continue
} else {
text = `'` + text;
text = `'` + text
}
}
type = 'text';
text += `']`;
type = 'text'
text += `']`
}
}
targets.push({label: property.name, text, type, start: i, length: property.name.length });
targets.push({
label: property.name,
text,
type,
//start: i,
length: property.name.length,
})
}
}
// If we found the variable in one context (typically Locals), abort
break;
break
}
}
}
response.body = {targets};
console.log(`completionsRequest ${args.text} (${args.column}:${args.line}) ${JSON.stringify(targets)}`)
response.body = { targets }
} catch (err) {
this.sendErrorResponse(response, err);
return;
this.sendErrorResponse(response, err)
return
}
this.sendResponse(response);
this.sendResponse(response)
}


protected async continueRequest(
response: VSCodeDebugProtocol.ContinueResponse,
args: VSCodeDebugProtocol.ContinueArguments
Expand Down
12 changes: 6 additions & 6 deletions src/test/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,12 +679,12 @@ describe('PHP Debug Adapter', () => {
})

describe('completion', () => {
it('should provide completion for local variables');
it('should provide completion for superglobals');
it('should provide completion for object properties');
it('should provide completion for numeric array indexes');
it('should provide completion for string array indexes');
});
it('should provide completion for local variables')
it('should provide completion for superglobals')
it('should provide completion for object properties')
it('should provide completion for numeric array indexes')
it('should provide completion for string array indexes')
})

describe.skip('output events', () => {
const program = path.join(TEST_PROJECT, 'output.php')
Expand Down
12 changes: 6 additions & 6 deletions src/xdebugConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,12 +632,12 @@ export class PropertyGetResponse extends Response {
children: Property[]
/**
* @param {XMLDocument} document
* @param {Property} property
* @param {Context} context
*/
constructor(document: XMLDocument, property: Property) {
super(document, property.context.stackFrame.connection)
constructor(document: XMLDocument, context: Context) {
super(document, context.stackFrame.connection)
this.children = Array.from(document.documentElement.firstChild!.childNodes).map(
(propertyNode: Element) => new Property(propertyNode, property.context)
(propertyNode: Element) => new Property(propertyNode, context)
)
}
}
Expand Down Expand Up @@ -1022,14 +1022,14 @@ export class Connection extends DbgpConnection {
}

/** Sends a property_get command */
public async sendPropertyGetCommand(property: Property): Promise<PropertyGetResponse> {
public async sendPropertyGetCommand(property: {context: Context, fullName: string}): Promise<PropertyGetResponse> {
const escapedFullName = '"' + property.fullName.replace(/("|\\)/g, '\\$1') + '"'
return new PropertyGetResponse(
await this._enqueueCommand(
'property_get',
`-d ${property.context.stackFrame.level} -c ${property.context.id} -n ${escapedFullName}`
),
property
property.context
)
}

Expand Down

0 comments on commit 95e0764

Please sign in to comment.