Skip to content
This repository has been archived by the owner on Aug 7, 2023. It is now read-only.

Fix/one spawn per project #83

Merged
merged 11 commits into from
Apr 21, 2018
Merged

Fix/one spawn per project #83

merged 11 commits into from
Apr 21, 2018

Conversation

cgalvarez
Copy link
Contributor

@cgalvarez cgalvarez commented Feb 25, 2018

This PR has the following goals:

  • Massive refactor of the code.
  • Analyze the whole project, not only the currently open file, so allowing for any engine and including previously missing issues like duplicated code.
  • Debounce the linting process, so multiple files from the same project can merge into one unique analysis.
  • Remove some code that doesn't make sense or it's outdated.
  • Fix all currently reported issues on CodeClimate. I've managed to comply with the cognitive complexity. Hope @Arcanemagus likes the final refactor 😉
  • Proper docblocks for each function.

And still waiting for the following bugs to be fixed in their respective repos:

There are some issues left that are very annoying, but I don't have any clue on how to fix them, and can be the subject of future PRs:

  • On the first Atom run (right after opening Atom for the first time or reloading it with control + shift + F5), the CLI is ran multiple times (typically two). The debounced linting cannot address this issue because the time between the executions exceeds 2s, and setting the debounce timeout to that feels overkilling, and make the whole point of this PR useless.
  • When starting Atom with multiple files open, changing from one to another still triggers a new analysis. This could be addressed to improve performance.
  • When starting Atom with multiple files open, the CodeClimate issues are generated correctly for AtomLinter, but they never get added. User need to manually re-trigger analysis by saving a file to get the issues included in AtomLinter pane.

Also, this PR...

Fixes #75
Fixes #76
Closes #77 with a temporary workaround
Fixes #81
Closes #69, since it should be supported by CodeClimate CLI in first place, and it should miss some issues (like duplicated code), which this PR aims to solve.
Closes #74
Closes #77
Closes #78

Edited by @Arcanemagus to automatically close issues/PRs.

@cgalvarez
Copy link
Contributor Author

The tests seem to hang, cannot make them even print any error.

Anyone that could lend me a hand on this? This PR can be installed and tested locally with:

git clone -b 'fix/one-spawn-per-project' https://github.com/cgalvarez/linter-codeclimate.git linter-codeclimate-pr
cd ./linter-codeclimate-pr
apm link --dev
apm install
atom -d .

@cgalvarez cgalvarez mentioned this pull request Feb 26, 2018
@cgalvarez
Copy link
Contributor Author

Wow, I was about to give up, but the tests take ~273s on CI to finish!! Locally ~20s. What an amazing difference... but finally get it working and passing!! 🎉 🎉 🎉

@EugeneGrigorenko
Copy link

Is it gonna be merged?

@Arcanemagus
Copy link
Member

Looks like the Code Climate people aren't maintaining this 😆😢.

Taking a look over this now, that diff summary looks daunting 😮.

Copy link
Member

@Arcanemagus Arcanemagus left a comment

Choose a reason for hiding this comment

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

Here's some issues, both logic and design, that I see from a quick first pass.

lib/index.js Outdated
@@ -1,88 +1,356 @@
'use babel';

/* eslint no-use-before-define:0 */
Copy link
Member

Choose a reason for hiding this comment

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

Is disabling this absolutely necessary? If so, this should be moved to the general ESLint configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After making all functions that access to properties/methods of the package object, this can be removed.

lib/index.js Outdated
@@ -120,163 +384,14 @@ export default {
},

provideLinter() {
const Helpers = require('atom-linter');
const configurationFile = '.codeclimate.yml';
return {
name: 'Code Climate',
grammarScopes: ['*'],
scope: 'file',
Copy link
Member

Choose a reason for hiding this comment

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

The readme section saying this only worked for single file analysis has been removed... which implies that results for any file can be returned. If that's the case this should be changed to project.

lib/index.js Outdated
if (path.file === undefined) return path;

// Fetch previously cached paths when available.
if (ccLinter.openOnTextEditor[path.file]) {
Copy link
Member

Choose a reason for hiding this comment

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

This is accessing properties of the package object, just make this a method of that object.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, ccLinter.openOnTextEditor is never populated, so this can be simplified to if (false), I'm guessing that's not what you intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. I forgot to populate that prop to cache project root and textEditor.

lib/index.js Outdated
ignoreExitCode: true,
};

if (ccLinter.disableTimeout || global.waitsForPromise) {
Copy link
Member

Choose a reason for hiding this comment

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

This is accessing properties of the package object, just make this a method of that object.

Copy link
Member

Choose a reason for hiding this comment

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

global.waitsForPromise should be replaced with atom.inSpecMode().

lib/index.js Outdated
const runCli = async (cwd) => {
const execOpts = {
cwd,
uniqueKey: cwd,
Copy link
Member

Choose a reason for hiding this comment

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

This should have the provider name added in case the user has multiple providers running on the same directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally agree. My fault!

Copy link
Member

Choose a reason for hiding this comment

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

I made the same mistake when first implementing uniqueKey usage, that's how I know it's an issue 😆.

lib/index.js Outdated
} catch (e) {
notifyError(e, 'Invalid JSON returned from CodeClimate. See the Console for details.');
// eslint-disable-next-line no-console
console.error('Invalid JSON returned from CodeClimate:', result);
Copy link
Member

Choose a reason for hiding this comment

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

Why not just console.error inside notifyError?

lib/index.js Outdated
*/
const fetchOpenFilepaths = () => {
const openFiles = {};
atom.workspace.textEditorRegistry.editors.forEach((textEditor) => {
Copy link
Member

Choose a reason for hiding this comment

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

atom.workspace.textEditorRegistry.editors is a private property, this should be atom.workspace.getTextEditors().

Also instead of calling this every single time, it might be better to do atom.workspace.observeTextEditors().

lib/index.js Outdated

// Exit early if issued file is not open
const file = join(path.project, issue.location.path);
if (!open[file]) return;
Copy link
Member

Choose a reason for hiding this comment

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

I would instead use something like findTextEditor to get the TextEditor for a file if one is available, if not return the best position you can. If the user then opens the file a TextEditor will be available and a more accurate position can be determined from that.

Once you start returning results for anything other than the active TextEditor that you are passed, you must change the scope to project, and since that allows you to send results for any path, there is no reason to only filter results to ones that the user has open.

lib/index.js Outdated
performance.clearMarks(startMark);
}
performance.mark(startMark);
const configurationFile = '.codeclimate.yml';
Copy link
Member

Choose a reason for hiding this comment

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

This should just be declared directly where it is being used, if later on this becomes something that needs configuring it can be changed then.

lib/index.js Outdated
const linting = {};
const fingerprints = {};
const debounceTimeout = 250;
const mapSeverity = {
Copy link
Member

Choose a reason for hiding this comment

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

I would leave this down in the function where it is used.

@cgalvarez
Copy link
Contributor Author

@Arcanemagus Thank you very much for detailed review. I'll take a look at all your reported issues ASAP and make a new commit to fix them all.

@cgalvarez
Copy link
Contributor Author

I've just fixed all your reported issues. Let me know If I've missed something or you want me to make a rebase or something 😉

I think it would be desirable to disable some Code Climate engines run in CI to make tests run faster.

Copy link
Member

@Arcanemagus Arcanemagus left a comment

Choose a reason for hiding this comment

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

Great work, thanks a ton for taking this on!


if (this.cache[path]) return;

textEditor.onDidDestroy(() => delete this.cache[path]);
Copy link
Member

Choose a reason for hiding this comment

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

Nice solution to keeping the cache but invalidating it when needed. The only potential issue is that you need to remember to re-populate it if the TextEditor's path is missing from the cache (which you did where needed 👍).

@Arcanemagus
Copy link
Member

Since CI is passing, and I can't run this locally (Windows), I'll go ahead and merge this. 😆

@Arcanemagus Arcanemagus merged commit 1456860 into AtomLinter:master Apr 21, 2018
@Arcanemagus
Copy link
Member

@cgalvarez Assuming @AtomLinter/linter-codeclimate has no issues with it, if you want to be brought on as a maintainer for this project I would be fine with that 😉.

@Arcanemagus
Copy link
Member

Published in v0.3.0 🎉.

@cgalvarez
Copy link
Contributor Author

@Arcanemagus Great! I will be glad to help anytime I can.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
3 participants