Skip to content
This repository was archived by the owner on Mar 25, 2021. It is now read-only.

Update dependencies and lint for no-unsafe-any#2544

Merged
nchen63 merged 8 commits intopalantir:masterfrom
andy-hanson:use_no-unsafe-any
Apr 17, 2017
Merged

Update dependencies and lint for no-unsafe-any#2544
nchen63 merged 8 commits intopalantir:masterfrom
andy-hanson:use_no-unsafe-any

Conversation

@andy-hanson
Copy link
Contributor

PR checklist

  • Addresses an existing issue: #0000
  • New feature, bugfix, or enhancement
    • Includes tests
  • Documentation update

Overview of change:

The no-unsafe-any rule mostly just required appropriate casts, but in the case of FormatterFunction it seems to have discovered a bug -- formatters actually seem to have to be new-able. So created a FormatterStatic instead. This is technically a breaking change, but code that compiled against FormatterFunction would have been wrong.


export type ConsumerType = "human" | "machine";

export interface FormatterStatic {
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to FormatterConstructor?


const moduleDirectory = path.dirname(module.filename);
const CORE_RULES_DIRECTORY = path.resolve(moduleDirectory, ".", "rules");
const cachedRules = new Map<string, typeof AbstractRule | null>(); // null indicates that the rule was not found
Copy link
Contributor

Choose a reason for hiding this comment

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

actually I found this to be clearer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But rules aren't actually guaranteed to be implemented by AbstractRule subclasses, are they?

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that it's renamed to RuleConstructor I'm fine with it.

import {arrayify, flatMap} from "../../utils";
import {IWalker} from "../walker";

export interface RuleStatic {
Copy link
Contributor

@ajafff ajafff Apr 11, 2017

Choose a reason for hiding this comment

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

also rename to RuleConstructor?


let Rule: typeof AbstractRule | null = null;
let Rule: RuleStatic | null = null;
if (absolutePath != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this comparison can be strict

@@ -87,7 +87,7 @@ class NoInferredEmptyObjectTypeRule extends Lint.ProgramAwareRuleWalker {
let isAnonymous: boolean;
if (ts.ObjectFlags == null) {
// typescript 2.0.x specific code
Copy link
Contributor

Choose a reason for hiding this comment

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

this branch can be removed since support for ts 2.0.x was dropped in v5.0.0

*/
export function camelize(stringWithHyphens: string): string {
return stringWithHyphens.replace(/-(.)/g, (_, nextLetter) => nextLetter.toUpperCase());
return stringWithHyphens.replace(/-(.)/g, (_, nextLetter) => (nextLetter as string).toUpperCase());
Copy link
Contributor

Choose a reason for hiding this comment

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

consider adding the type annotation to the parameter instead of asserting it

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 don't like that style since it behaves the same as a typecast but doesn't look like one. Was actually considering writing a lint rule for that.

Copy link
Contributor

Choose a reason for hiding this comment

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

um, I don't think that's quite right @andy-hanson. type assertions (as string) are generally less safe than typedefs, because the assignability checks for the latter are stricter

Copy link
Contributor Author

@andy-hanson andy-hanson Apr 13, 2017

Choose a reason for hiding this comment

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

A type annotation in a callback is unsafe.

declare function f(cb: (x: {}) => void): void;
f((n: number) => { console.log(n + 1); }); // Huh, no error?

A type assertion is of course also unsafe, but it's more obvious that it is.

}
}
return undefined;
return null;
Copy link
Contributor

Choose a reason for hiding this comment

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

why the switch to nulls? can't we use undefined?

Copy link
Contributor Author

@andy-hanson andy-hanson Apr 13, 2017

Choose a reason for hiding this comment

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

We use cachedRules.set(fullPath, Rule);, so if Rule is undefined, it will look like we didn't cache a result at all. I actually already had to do this in #2369.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe we should use a string literal like "not-found" or "load-error" instead of null

*/
export function camelize(stringWithHyphens: string): string {
return stringWithHyphens.replace(/-(.)/g, (_, nextLetter) => nextLetter.toUpperCase());
return stringWithHyphens.replace(/-(.)/g, (_, nextLetter) => (nextLetter as string).toUpperCase());
Copy link
Contributor

Choose a reason for hiding this comment

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

um, I don't think that's quite right @andy-hanson. type assertions (as string) are generally less safe than typedefs, because the assignability checks for the latter are stricter

} catch (error) {
if (error.name === FatalError.NAME) {
console.error(error.message);
if ((error as FatalError).name === FatalError.NAME) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you use error: FatalError on the line above instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, TS doesn't allow a type annotation there. It wouldn't be safe anyway since TS doesn't have checked exceptions.

/* tslint:enable:object-literal-sort-keys */

public static FAILURE_STRING = "Unsafe use of expression of type 'any'.";
public static FAILURE_STRING: string = "Unsafe use of expression of type 'any'.";
Copy link
Contributor

Choose a reason for hiding this comment

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

surely this isn't necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, no idea why that got there!


public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const limit: number = this.ruleArguments[0] || Rule.DEFAULT_ALLOWED_BLANKS;
const limit = this.ruleArguments[0] as number | undefined || Rule.DEFAULT_ALLOWED_BLANKS;
Copy link
Contributor

Choose a reason for hiding this comment

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

why the switch from typedef to type assertion?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A typedef const x: number = thisIsAny; is flagged by the no-unsafe-any rule, since it looks safe but isn't. const x = thisIsAny as number; is OK since that's obviously an assertion.

@andy-hanson andy-hanson mentioned this pull request Apr 13, 2017
4 tasks
function getHomeDir() {
function getHomeDir(): string | undefined {
const environment = global.process.env;
const paths = [
Copy link
Contributor

@nchen63 nchen63 Apr 16, 2017

Choose a reason for hiding this comment

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

prefer type annotation on paths instead of the function return value. or both

const ruleSpecificList = enableDisableRules || [];
ruleOptions.disabledIntervals = buildDisabledIntervalsFromSwitches(ruleSpecificList);
rules.push(new (Rule as any)(ruleOptions));
rules.push(new (Rule as any)(ruleOptions) as IRule);
Copy link
Contributor

Choose a reason for hiding this comment

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

don't need either cast

* limitations under the License.
*/

// tslint:disable no-unsafe-any (TODO)
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this needed?

if (fs.existsSync(`${fullPath}.js`)) {
const formatterModule = require(fullPath);
return formatterModule.Formatter;
return formatterModule.Formatter; // tslint:disable-line no-unsafe-any
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of disabling rule, cast the require to an interface like { Formatter: FormatterConstructor }

return undefined;
}
return require(src).Formatter;
return require(src).Formatter; // tslint:disable-line no-unsafe-any
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above comment

}
}
return undefined;
return null;
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe we should use a string literal like "not-found" or "load-error" instead of null

Rule = loadRule(absolutePath, ruleName);
let Rule: RuleConstructor | null = null;
if (absolutePath !== undefined) {
Rule = loadRule(absolutePath, ruleName); // tslint:disable-line no-unsafe-any
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need to disable the rule here

}

// tslint:disable-next-line no-unsafe-any
return { order: categoryFromOption(firstOption[OPTION_ORDER]), alphabetize: !!firstOption[OPTION_ALPHABETIZE] };
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of disabling, annotate firstOption as type Options, then call using firstOption.order and firstOption.alphabetize

* limitations under the License.
*/

// tslint:disable no-unsafe-any (TODO)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need to disable the rule here

Copy link
Contributor

@nchen63 nchen63 left a comment

Choose a reason for hiding this comment

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

just some nits

}

/**
/**findRule
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this here?

const moduleDirectory = path.dirname(module.filename);
const CORE_RULES_DIRECTORY = path.resolve(moduleDirectory, ".", "rules");
const cachedRules = new Map<string, typeof AbstractRule | null>(); // null indicates that the rule was not found
const cachedRules = new Map<string, RuleConstructor | "not-found">(); // null indicates that the rule was not found
Copy link
Contributor

Choose a reason for hiding this comment

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

can remove/update this comment

@nchen63 nchen63 merged commit a3d8d6f into palantir:master Apr 17, 2017
@andy-hanson andy-hanson deleted the use_no-unsafe-any branch April 18, 2017 00:40
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.

4 participants