Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use yaml package when selecting build configs #351

Merged
merged 8 commits into from
Apr 22, 2021
Merged

Use yaml package when selecting build configs #351

merged 8 commits into from
Apr 22, 2021

Conversation

wwlorey
Copy link
Contributor

@wwlorey wwlorey commented Apr 12, 2021

Yaml values without quotes are supported now as well:
Screen Shot 2021-04-21 at 12 34 22 PM

Fixes #349

@wwlorey wwlorey requested a review from a team as a code owner April 12, 2021 21:27
src/commands/openYAMLConfigFile.ts Show resolved Hide resolved
src/commands/openYAMLConfigFile.ts Outdated Show resolved Hide resolved
// The range returned from the `yaml` package doesn't include newlines
// So count newlines and include them in the range we return
for (const char of configDocumentText.slice(0, buildConfigOffset)) {
newlines += char === '\n' ? 1 : 0;
Copy link

Choose a reason for hiding this comment

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

There seems to be another way to do this without the for-loop.
Will, you might have already looked at this, but wondering if we can use this method instead?
eemeli/yaml#127 (comment)

Also, should we track this issue? In case there is an improvement from the yaml side.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion - now this is using only the yaml package to get ranges. I don't think we need to track the issue though. From the looks of it they've already rejected the feature request to include newline counts in ranges

Copy link
Contributor

@ejizba ejizba left a comment

Choose a reason for hiding this comment

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

I'm generally only okay with disabling lint on a per-line basis. In this case, we can just fix the lint problems instead of disabling them - see suggestions

Comment on lines 62 to 64
type YamlNode = YAMLMap | YAMLSeq | Pair | undefined;
const yamlNodes: YamlNode[] = [];
let yamlNode: YamlNode = parsedYaml.get('jobs');
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to hard-code "jobs" if we just use the root "contents"

Suggested change
type YamlNode = YAMLMap | YAMLSeq | Pair | undefined;
const yamlNodes: YamlNode[] = [];
let yamlNode: YamlNode = parsedYaml.get('jobs');
type YamlNode = YAMLMap | YAMLSeq | Pair | Scalar | undefined | null;
const yamlNodes: YamlNode[] = [];
let yamlNode: YamlNode = parsedYaml.contents;

Comment on lines 67 to 69
if (yamlNode.hasOwnProperty('key') && yamlNode['key'].value === buildConfigToSelect && yamlNode.hasOwnProperty('value')) {
const configValue = <Scalar>yamlNode['value'];
const range = <number[] | undefined>configValue.range;
Copy link
Contributor

Choose a reason for hiding this comment

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

Fixing lint errors

Suggested change
if (yamlNode.hasOwnProperty('key') && yamlNode['key'].value === buildConfigToSelect && yamlNode.hasOwnProperty('value')) {
const configValue = <Scalar>yamlNode['value'];
const range = <number[] | undefined>configValue.range;
if ('key' in yamlNode && (<Scalar>yamlNode.key).value === buildConfigToSelect && 'value' in yamlNode) {
const configValue = <Scalar>yamlNode.value;
const range = configValue.range;

Comment on lines 103 to 107
} else if (yamlNode.hasOwnProperty('items')) {
yamlNodes.push(...yamlNode['items'])
} else if (yamlNode.hasOwnProperty('value') && yamlNode['value'].hasOwnProperty('items')) {
yamlNodes.push(...yamlNode['value']['items'])
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Fixing lint errors and seems easier to pop yamlNode.value onto the queue rather than dig into items in multiple places

Suggested change
} else if (yamlNode.hasOwnProperty('items')) {
yamlNodes.push(...yamlNode['items'])
} else if (yamlNode.hasOwnProperty('value') && yamlNode['value'].hasOwnProperty('items')) {
yamlNodes.push(...yamlNode['value']['items'])
}
} else if ('items' in yamlNode) {
yamlNodes.push(...yamlNode.items);
} else if ('value' in yamlNode && typeof yamlNode.value === 'object') {
yamlNodes.push(yamlNode.value)
}

async function getSelection(configDocument: TextDocument, buildConfigToSelect: BuildConfig): Promise<Range | undefined> {
const configRegex: RegExp = new RegExp(`${buildConfigToSelect}:`);
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, no-prototype-builtins, @typescript-eslint/no-unsafe-assignment */
export async function getSelection(configDocument: TextDocument, buildConfigToSelect: BuildConfig): Promise<Range | undefined> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the code is a bit complex and has some sketchy "any" types, I'd probably rename this to tryGetSelection and add a big try/catch that just returns undefined if an error happens. This function already allows | undefined in the return type anyways

const workspacePath: string = getWorkspacePath('testWorkspace');

test(title, async () => {
const configDocument: TextDocument = await workspace.openTextDocument(join(workspacePath, 'testWorkflows', testCase.workflowFileName));
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than use separate yml files in the "testWorkflows" directory, I'd prefer you just put the test data in this file (like, as a const), for a few reasons:

  1. Using the file system and/or VS Code APIs can slow tests down. It's worth it for end-to-end tests, but overkill for unit tests IMO
  2. You can easily manipulate the test data with template literals and whatnot
  3. Idk just seems easier to read when the test data is in the same file.

I feel like the only downside is this file can get pretty long, but it just doesn't bother me 🤷‍♂️. One way to help with that is to scope your test data down to smaller cases. For example, you might have one test running against an "actual" yml file seen in the wild, but the other tests are usually just testing specific edge cases without the full "yml" file necessary.

@wwlorey wwlorey changed the title Select entire line when clicking GitHub config tree item Use yaml package when selecting build configs Apr 21, 2021
interface ISelectBuildConfigTestCase {
workflowIndex: number;
buildConfig: BuildConfig;
expectedSelection: undefined | {
Copy link
Member

Choose a reason for hiding this comment

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

nit: I don't think I've ever seen anyone list undefined first in a | type haha

expectedSelection = new Range(expectedStart, expectedEnd);
}

assert.ok(expectedSelection && selection?.isEqual(expectedSelection) || selection === expectedSelection, 'Actual and expected selections do not match');
Copy link
Member

Choose a reason for hiding this comment

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

You should be able to use assert.strictEquals() here. Using assert.ok seems kind of roundabout here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went with assert.ok because comparing two ranges uses their isEqual() function. I updated the assert to hopefully make it look more purposeful

Copy link
Member

Choose a reason for hiding this comment

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

Ahh, okay, makse sense.

azure_static_web_apps_api_token: $\{{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_ROCK_0D992521E }}
action: "close"

`];
Copy link
Member

Choose a reason for hiding this comment

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

Could we try location paths with special characters and maybe some foreign characters? (Chinese or Korean or something seems plausible)

@wwlorey wwlorey merged commit 8843883 into main Apr 22, 2021
@wwlorey wwlorey deleted the wwl/range branch April 22, 2021 23:20
@github-actions github-actions bot locked and limited conversation to collaborators Jun 7, 2021
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.

The updated config value without a "" is not highlight after clicking the config tree item
4 participants