Skip to content

Conversation

@ericsnowcurrently
Copy link

@ericsnowcurrently ericsnowcurrently commented Aug 28, 2018

(fixes #1948)

  • Title summarizes what is changing
  • Has a news entry file (remember to thank yourself!)
  • Has unit tests & system/integration tests
  • Any new/changed dependencies in package.json are pinned (e.g. "1.2.3", not "^1.2.3" for the specified version)
  • package-lock.json has been regenerated by running npm install (if dependencies have changed)

This is a derivative of @DonJayamanne's #2197. Differences:

  • removes extra Jedi-related changes
  • PythonSymbolProvider -> JediSymbolProvider
  • SymbolProvider -> LanguageServerSymbolProvider (and moved to src/client/providers/symbolProvider.ts)
  • flattens the symbol data returned from the language server
  • works around a bug in the language server (off-by-one kind)
  • adds tests for LanguageServerSymbolProvider

@ericsnowcurrently
Copy link
Author

FWIW, I don't see any difference with this PR applied locally. Code lenses are not showing up (whereas they do for Jedi)...

@ericsnowcurrently
Copy link
Author

ericsnowcurrently commented Aug 29, 2018

I used the repro case detailed in #1948 (comment).

@ericsnowcurrently ericsnowcurrently changed the title [WIP] Use symbol provider from new language server to place code lenses in tests. Use symbol provider from new language server to place code lenses in tests. Aug 29, 2018
@ericsnowcurrently
Copy link
Author

Looks like the data returned from the language server doesn't work quite right. I'll open an issue (or two) as soon as I can. I'm also going to work around the problem for now.

@ericsnowcurrently
Copy link
Author

I've opened Language Server issue for things I've had to work around:

Other than that, I had to flatten the data returned from the language server. :)

Copy link

@d3r3kk d3r3kk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need a news file, and other than that maybe have a look at the comments made on the recursive routine, I'd love to see us not create new objects with each iteration and copy them (and their members) about. If we can get rid of the call .push(...flattenedChild) and instead push each flattened child into the list as it progresses that might help with perf/memory on larger projects.

}

function flattenSymbolTree(tree: ILSSymbolTree, uri: Uri, containerName: string = ''): SymbolInformation[] {
const flattened: SymbolInformation[] = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can somehow pass this in as a reference, it might cheapen up the resource cost of this recursion.

args,
token
);
const symbols: SymbolInformation[] = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be the value you send into the recursive routine to avoid creating new objects.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, the API should return an array rather than us passing a state bag that needs to be populated.
Internally the function can use a single array that is passed by ref.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning items is better than passing a state bag, e.g if the cost is very expensive then we can always use generators (with yield), that works perfectly here. But if we passed a state bag there's no way to use yield.

@d3r3kk
Copy link

d3r3kk commented Aug 30, 2018

Approving the changes after a fun academic conversation with @ericsnowcurrently on the cost/benefit and the true costs of his solution vs. my proposal. We are only ever traversing a single file gathering these symbols. Unless that single file is wonderfully complicated in terrible ways, the perf of this solution is not going to be a problem.

👍

@ericsnowcurrently ericsnowcurrently force-pushed the fix-1948-ls-test-code-lenses branch from cbad124 to 631b69a Compare August 30, 2018 22:28
Copy link

@DonJayamanne DonJayamanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

* 'x.y' -> ['x', 'y']
* 'x' -> ['', 'x']
* 'x.y.z' -> ['x.y', 'z']
* '' -> ['', '']

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is illogical. You can't have a parent if name is empty.
It should return undefined, instead of returning incorrect info. This leads to the assumption that there is a parent when there isn't.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point in a general sense. However, in this case how is '' different from undefined? Using undefined for this seems like more work for everyone.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

however that's poor API design!!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to discuss this more, perhaps in teams, etc. We're not communicating well about this over github. :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and I want to make sure we're on the same page with this sort of stuff.

* A representation of the symbol data the language server provides.
*/
interface ILSSymbolTree {
name: string;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remember, use interfaces only when implementing them in classes. Else use types

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. This was an attempt to get type conversion to work right. I ended up doing it a different way but forgot to remove the interface. :)

detail?: string;
}
interface IRange {
start: IPosition;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely there must be an existing interface we can use for this? Why can't we use what's in VSC?
I can't see where these are used internally!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. :) This was also left over from trying to use type conversion.

if (!symbols) {
return [];
}
return symbols!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need of !

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is your code, not mine. :) I'll fix it.

* '' -> ['', '']
*/
export function splitFullName(fullName: string): [string, string] {
if (fullName.length === 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this function into a separate file such a languageUtils.js, else this file here annoyed to store everything and it's become a very large bag of tricks!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll split up utils.ts in a separate PR.

args,
token
);
const symbols: SymbolInformation[] = [];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, the API should return an array rather than us passing a state bag that needs to be populated.
Internally the function can use a single array that is passed by ref.

args,
token
);
const symbols: SymbolInformation[] = [];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning items is better than passing a state bag, e.g if the cost is very expensive then we can always use generators (with yield), that works perfectly here. But if we passed a state bag there's no way to use yield.


suite('Language Server Symbol Provider', () => {

function newLanguageClient(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to use a verb, such as createLanguageClient or get..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

});

function newDoc(
uri?: Uri,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to createDoc or getDoc, or similar.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

// helpers

function newSymbols(
uri: Uri,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to use a verb in the function name.
E.g. create, get, parse, etc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@ericsnowcurrently ericsnowcurrently dismissed DonJayamanne’s stale review August 31, 2018 18:48

I'm going to merge this with only a couple of Don's concerns still open. We can address those separately.

@ericsnowcurrently ericsnowcurrently merged commit 90d1e4a into microsoft:master Aug 31, 2018
@ericsnowcurrently ericsnowcurrently deleted the fix-1948-ls-test-code-lenses branch August 31, 2018 18:50
ericsnowcurrently added a commit that referenced this pull request Sep 5, 2018
This is a follow-up to #2456. I've pulled many of the "util" modules out of src/client/common into a new sibling package to client: utils. This helps us separate the extension-specific code from the generic code we use for the extension.
@lock lock bot locked as resolved and limited conversation to collaborators Jul 31, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code Lenses not appearing in Unit Tests when using the new language server

3 participants