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

Adding command to fix TS files + other changes (see desc.) #149

Merged
merged 4 commits into from
Apr 9, 2017
Merged

Adding command to fix TS files + other changes (see desc.) #149

merged 4 commits into from
Apr 9, 2017

Conversation

Xapphire13
Copy link
Contributor

  • Adding command to fix TS files.
  • Added option to skip .d.ts files.
  • Adding linter name so that it appears in the history log.

…ing linter name so that it appears in the history log.
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 a first pass review. I'm still not entirely sure about adding classes to the editors, but I can't see any harm to it and it does let the command only show up for files where it would make sense, which is a nice touch.

lib/main.js Outdated
atom.config.observe('linter-tslint.useLocalTslint', (use) => {
tslintCache.clear();
this.useLocalTslint = use;
}),
);

atom.workspace.observeActivePaneItem((activeItem) => {
Copy link
Member

Choose a reason for hiding this comment

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

Why observeActivePaneItem instead of observeTextEditors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lack of API knowledge =], will update, thanks

lib/main.js Outdated
* @return {boolean} Whether or not the grammar is for TypeScript
*/
function isTypescriptGrammar(grammar) {
return grammar.fileTypes.find(fileType => /.*ts/i.test(fileType));
Copy link
Member

Choose a reason for hiding this comment

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

Please put a note that this is not part of the public API if we can't find a way around using this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you elaborate what you mean by non-public API here? This is my first modification of an Atom package and am unaware of how else to do helper methods.

Copy link
Member

Choose a reason for hiding this comment

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

Anything that isn't listed in the Atom Docs isn't part of the public API, and is subject to change at any time 😉.

In this case the Grammar object you are accessing is very bare bones, and doesn't expose a way to get to the fileTypes property you are utilizing here. This comment shows a way around all this 😉.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it! Thanks for the detailed explanation

lib/main.js Outdated
atom.commands.add(`atom-text-editor.${editorClass}`, {
'linter-tslint:fix-file': () => {
const textEditor = atom.workspace.getActiveTextEditor();
// const filePath = textEditor.getPath();
Copy link
Member

Choose a reason for hiding this comment

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

No reason to bring in commented out code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, I missed that thanks!

lib/main.js Outdated

atom.workspace.observeActivePaneItem((activeItem) => {
if (activeItem && activeItem.getGrammar) {
if (isTypescriptGrammar(activeItem.getGrammar())) {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of using a non-public API can we validate it based on scopes like everything else with linter providers is done?

You can find an example of how to use the cursors to get the scopes and check it using the public API from linter-eslint 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.

Went with a solution i found in the Atom api that seemed simpler.

lib/main.js Outdated
if (!textEditor || textEditor.isModified()) {
// Abort for invalid or unsaved text editors
atom.notifications.addError('Linter-TSLint: Please save before fixing');
return Promise.resolve();
Copy link
Member

Choose a reason for hiding this comment

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

Just mark the function as async here and all return values will be Promises. You can also use await on the lint() call, as well as getting rid of the chained then() calls.

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 though async/await didn't make the ES6 spec and wasn't going to have wide support until ECMA 2017. I will change and test it out though

Copy link
Member

Choose a reason for hiding this comment

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

Atom has built in transpilation of all package files that start with 'use babel';, as well as having a relatively new version of Node.js, so new features like that are usable in Atom.

lib/main.js Outdated
rulesDirectory.push(this.rulesDirectory);
}
}
if (atom.config.get('linter-tslint.ignoreTypings') && /.*\.d\.ts$/i.test(textEditor.getPath())) {
Copy link
Member

Choose a reason for hiding this comment

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

This setting should be observe()'d like the others.

Copy link
Member

Choose a reason for hiding this comment

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

Also, how about this for the second part? If the case-insensitivity is important add a .toLowerCase() in there.

textEditor.getPath().endsWith('.d.ts')

@Arcanemagus
Copy link
Member

Thanks for taking this on btw!

I don't use TypeScript myself, and it seems the people that were maintaining this have abandoned it unfortunately so it's needed some attention for a while.

@Xapphire13
Copy link
Contributor Author

I have updated with the changes requested. Is anything else needed from me now? (Still new to GitHub PRs)

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.

More thorough review now that I'm sure the command thing is something that should happen 😉.

Some of this might just be inherited issues exposed due to moving the lint() code out into it's own function, but we might as well fix it now.

lib/main.js Outdated
// we can enable commands only for TypeScript editors.
this.subscriptions.add(
atom.workspace.observeTextEditors((textEditor) => {
if (textEditor.getRootScopeDescriptor().scopes.some(scope => scope === typescriptScope)) {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of accessing .scopes directly, use getScopesArray().

Copy link
Member

Choose a reason for hiding this comment

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

Also, the scopes allowed by the provider here should be used, so typescriptScope should rather be typeScriptScopes and be an array equal to those scopes (the definiton down there should just be a reference to the same array), then the check function should be:

textEditor.getRootScopeDescriptor().getScopesArray().some(scope => typeScriptScopes.includes(scope))

(This is pushing this line rather long, might want to split it up)

lib/main.js Outdated
@@ -8,6 +8,8 @@ import fs from 'fs';
import requireResolve from 'resolve';

const TSLINT_MODULE_NAME = 'tslint';
const typescriptScope = 'source.ts';
const editorClass = 'typescript-editor';
Copy link
Member

Choose a reason for hiding this comment

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

Let's make this very specific, maybe something like linter-tslint-compatible-editor?

lib/main.js Outdated
this.subscriptions.add(
atom.workspace.observeTextEditors((textEditor) => {
if (textEditor.getRootScopeDescriptor().scopes.some(scope => scope === typescriptScope)) {
textEditor.element.classList.add(editorClass);
Copy link
Member

Choose a reason for hiding this comment

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

This definitely isn't compatible with the public API, does this get you what you need?

atom.views.getView(textEditor);

That should at least get you the proper DOM element through the API.

lib/main.js Outdated

// The fix replaces the file content and the cursor jumps automatically
// to the beginning of the file, so save current cursor position
const cursorPosition = textEditor.getCursorBufferPosition();
Copy link
Member

Choose a reason for hiding this comment

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

Just a note: This only happens sometimes, and when it does happen, restoring the cursor like this for some reason doesn't seem to work from the limited testing from AtomLinter/linter-eslint#853 (it hasn't been pushed out to the public yet).

lib/main.js Outdated
} catch (err) {
atom.notifications.addWarning(err.message);
} finally {
// set cursor to the position before fix job
Copy link
Member

Choose a reason for hiding this comment

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

"set" -> "Set" (or "Restore"?)

lib/main.js Outdated
const linter = new Linter(Object.assign({
formatter: 'json',
rulesDirectory,
}, options));
Copy link
Member

Choose a reason for hiding this comment

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

Does it handle undefined being passed in here? If not, you need a default specified up on L179.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

undefined is handled yes

lib/main.js Outdated

linter.lint(filePath, text, configuration);
const lintResult = linter.getResult();
lint(textEditor, options) {
Copy link
Member

Choose a reason for hiding this comment

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

Declare this as async lint(textEditor, options) {...

lib/main.js Outdated
// Text has been modified since the lint was triggered, tell linter not to update
return null;
}
return this.getLinter(filePath).then((Linter) => {
Copy link
Member

Choose a reason for hiding this comment

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

And then await on this.

Copy link
Member

Choose a reason for hiding this comment

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

(Note that getLocalLinter and getLinter could be re-written in this manner as well if you wanted.)

lib/main.js Outdated
return [];
let { rulesDirectory } = configuration;
if (rulesDirectory) {
const configurationDir = path.dirname(configurationPath);
Copy link
Member

Choose a reason for hiding this comment

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

dirname will throw a deprecation if configurationPath is null or undefined, is this a possibility? You probably need a check in here to handle that, as well as the usages further down.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code was already here so I'm not an expert in it's behavior.

lib/main.js Outdated
let { rulesDirectory } = configuration;
if (rulesDirectory) {
const configurationDir = path.dirname(configurationPath);
if (!Array.isArray(rulesDirectory)) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this for backwards compatibility with older tslint versions? Maybe put a comment in here for the reasoning behind this.

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 have no idea, this code was here before my change and is just moving with my refactoring of the method

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.

Sorry I missed this till just now!

@Arcanemagus Arcanemagus merged commit daf6a23 into AtomLinter:master Apr 9, 2017
@Arcanemagus
Copy link
Member

@Xapphire13 Would you be interested in helping to maintain this package?

@Xapphire13
Copy link
Contributor Author

@Arcanemagus Yes, I'd love to help maintain this package =]

@Arcanemagus
Copy link
Member

@Xapphire13 Invite sent, if you have any questions feel free to bug me on Atom's Slack, there is also a #linter and #linter-plugin-dev channel there if I'm not around.

Thanks for taking this up!

@Xapphire13 Xapphire13 deleted the fixts branch April 10, 2017 17:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants