GithubHelp home page GithubHelp logo

nicoespeon / hocus-pocus Goto Github PK

View Code? Open in Web Editor NEW
34.0 34.0 6.0 21.76 MB

VS Code extension that makes useful things appear out of the void (JS & TS) ๐Ÿ”ฎ

Home Page: https://marketplace.visualstudio.com/items?itemName=nicoespeon.hocus-pocus

License: MIT License

JavaScript 3.70% TypeScript 96.30%
javascript react typescript utilities vscode vscode-extension

hocus-pocus's Introduction

Hi there, welcome ๐Ÿ‘‹

My name is Nicolas Carlo and I help people build maintainable softwares!

About me

I live in Montrรฉal (Canada ๐Ÿ) and I'm a Freelance Web Developer specialized in legacy codebases.

I'm really into community events ๐Ÿป and Iย organize the Software Crafters, React, and TypeScript meetups in Montrรฉal. I'm also the organizer of The Legacy of SoCraTes conferences. I give talks too!

I frequently share advice to help you deal with Legacy Code on my blog Understand Legacy Code. I even published on book to share the techniques that work best:ย Legacy Code: First Aid Kit โ›‘

I'm the author of Abracadabra, a VS Code extension for intuitive JS/TS refactorings ๐Ÿ”ฎ

The best way to reach me out is through Twitter: @nicoespeon

hocus-pocus's People

Contributors

automatensalat avatar dependabot[bot] avatar nickebbitt avatar nicoespeon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

hocus-pocus's Issues

Create Variable creates invalid syntax in variable declarations

Describe the bug

When you execute the "Create Variable" action within the definition of an object literal the extension creates the variable declaration inside of the literal, generating invalid code.

How to reproduce

const myObj = {
    hello: "world",
    magicNumber: myNumber
  };

Execute Create Variable for myNumber. This gets generated:

const myObj = {
    hello: "world",
    magicNumber: const myNumber = ;
    myNumber
  };

Expected behavior

The variable should be declared outside of the literal block, like this:

const myNumber = ;
const myObj = {
    hello: "world",
    magicNumber: myNumber
  };

Additional information

  • Version of the extension impacted: v1.2.0

"Insert type" quick fix

Is this request related to a problem? Please describe.

Typescript can infer a lot of things and this helps with rapid development, but at some stage I usually like to put more types on my implicitly typed variables. And this kind of quick fix would be of a great help.

Describe the solution you'd like

Suppose we have implicitly typed variables especially in the form of destructuring.

const { a, b, c } = { a: 1, b: 2, c: "s" };

While cursor is inside const keyword there will be a quick fix "Insert type" that can add type like this

const { a, b, c }: { a: number; b: number; c: string } = { a: 1, b: 2, c: "s" };

This is the most complicated, but real world case. I'm trying to convert function with implicitly typed positional arguments into function that takes an object as an argument and this kind of quick fix would help me a lot.

Additional context

It would be great if this quick fix will be able to add types to any implicitly typed variable or function or object definition.

I think this could reuse some code from #3 feature request

Generate async function when invoked with await

Describe what's missing

When the "generate function" feature of the extension is invoked on code that has the await modifier, I expect the generated function to come with a async modifier.

How would it work

The extension would check if the not-yet-existing function has the await keyword or not. If yes, then async is prepended to the generated function.

Expected behavior

E.g.

const result = await doSomething();

Would generate

async doSomething() {
}
  • Version of the extension used: v1.1.0

Create function should work with function references

Describe what's missing

For code like this:

[1, 2, 3].forEach(print);

the extension only provides the Create Variable action for print. Instead, it would be nice to be able to create a function out of this too.

How would it work

I guess for the general case we'd need the infered types (#3).
Perhaps we could introduce a special case for forEach functions until then.
For functions called forEach we'd generate a function signature that takes 1 parameter and returns void.

This could work with map and filter as well.

Expected behavior

The extension provide the Create Function action to create a matching function if executed on a function reference used as a function parameter.

Additional information

  • Version of the extension used: v1.2.0

Use inferred types for function parameters in typescript

Hey @nicoespeon, thanks for the recommendation, this extension is what I was looking for.

Describe what's missing

When using Typescript and invoking the "extract function" feature I'd like the generated code to use the declared or inferred Typescript types for function parameters and return types if possible.

How would it work

The extension would use some internal system which provides the Typescript types and use those when generating declaring the function declaration.

Expected behavior

E.g. if I have this code

  const a = 3;
  const b = "hello";
  const c: MyType[] = [];
  const result: boolean = doSomething(a, b, c);

I'd like the generated code to be

 function doSomething(a: number, b: string, c: MyType[]): boolean {
   
 }

Additional information

  • Version of the extension used: v1.1.0

Code Action dropped in VSCode

Describe the bug

VSCode Extension Host displays the warning: "2022-12-21 15:02:42.636 [warning] nicoespeon.hocus-pocus - Code actions of kind 'quickfix 'requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'."

Expected behavior

No warnings were thrown.

Additional information

  • Version of the extension impacted: _ v1.7.0 _

๐Ÿ”ฎโ€ Add any other context about the problem here.
Not sure about the actual impact, but seeing that warning repeated seven times in the extension host output.

Add types to the 'create class' quick fix

Is this request related to a problem? Please describe.

The create class quick-fix does not currently infer types. Introduction of the type checker in #3 should allow us to enhance (or provide an alternative quick-fix) that provides typing.

Describe the solution you'd like

Given the code:

new MyClass('some string', 1234)

the quick-fix would generate a class with types for the constructor args:

class MyClass {
  constructor(param1: string, param2: number) {
    // Implement
  }
}

Creating a variable in `if` expression results in a mess

Describe the bug

When I created a variable for a variable name in an if condition expression, new code was added in that condition instead of before it.

How to reproduce

function test(n){
  if (n > max){
    // ...
  }
}

Create variable "max".

Then you will get:

function test(n){
  if (const max = ;
  n > max){
    // ...
  }
}

Expected behavior

function test(n){
  const max = ;
  if (n > max){
    // ...
  }
}

Create Function with Type generates "typeof" when used with Enums

Describe the bug

When executing hocusPocus.createFunctionWithTypes on code like this:

enum Bla {
	A = 1,
	B = 2,
}

function bla() {
	doSomething(Bla.A);
}

It generates typeof <Enum> instead of <Enum> as the parameter type in the created function:

function doSomething(param1: typeof Bla) {
  // Implement
}

TS will then complain about the argument not being assignable to the type of the parameter at the call site.

How to reproduce

Define an enum and pass a enum value to an unknown function, execute the extension.

Expected behavior

The extension should instead declare the parameter as the enum type, like this

function doSomething(param1: Bla) {
  // Implement
} 

Additional information

  • Version of the extension impacted: v1.4.0

Generate default stubbed implementation of interface for test purpose.

Is this request related to a problem? Please describe.

I'm new to Typescript and really enjoy coding in a typed world.
In the codebase I am getting in, usage of interfaces is quite heavy which is great for dependency injection and proper abstraction.
Something I find quite painful is to have a default implementation for interfaces ready to be spied in Unit Tests.
One way to solve that would have a Quick Action from Abracadabra generating this default implementation.

Describe the solution you'd like

I had this solution idea when reading this thread: https://stackoverflow.com/questions/37027776/how-to-stub-a-typescript-interface-type-definition. Especially the edit part of this answer: https://stackoverflow.com/a/37064529.

It could generate something like :

const defaultImplementation = <Interface>{};
defaultImplementation.a = sinon.stub();
defaultImplementation.b = sinon.stub();

Additional context

Feel free to ask for additional information.

Create Function with Types crashes when argument is an array

Describe the bug

When using the "Create function" (with types) action on a function that takes an array the action is not provided as a code fix. If I execute it via the command palette I receive an error:

// hocuspocus.ts
function bla() {
	const c: number[] = [1, 2, 3];
	doSomething(c);
}

Select doSomething and perform the action ->

Something went wrong: Error: Cannot find module 'typescript'
Require stack:
- /home/tobias/.vscode/extensions/nicoespeon.hocus-pocus-1.4.0/out/extension.js
- /usr/share/code/resources/app/out/vs/loader.js
- /usr/share/code/resources/app/out/bootstrap-amd.js
- /usr/share/code/resources/app/out/bootstrap-fork.js

How to reproduce

Just copy the above code into a .ts file and perform the action on doSomething.

Expected behavior

It should generate the function with the correct param type, in this case number[].

Additional information

  • Version of the extension impacted: v1.4.0

Here's my installed TS versions if it helps:

# TS not installed globally
tobias@tobias-Precision-3541:~/git/lofino-backend$ npm ls -g | grep typescript
โ”‚ โ”‚ โ”‚ โ”‚   โ”œโ”€โ”ฌ @babel/[email protected]
โ”‚ โ”‚ โ”‚ โ”‚   โ”‚ โ””โ”€โ”ฌ @babel/[email protected]
tobias@tobias-Precision-3541:~/git/lofino-backend$ npm ls | grep typescript
โ”œโ”€โ”ฌ @typescript-eslint/[email protected]
โ”‚ โ”œโ”€โ”ฌ @typescript-eslint/[email protected]
โ”‚ โ”‚ โ”œโ”€โ”€ @typescript-eslint/[email protected] deduped
โ”œโ”€โ”ฌ @typescript-eslint/[email protected]
โ”‚ โ”œโ”€โ”€ @typescript-eslint/[email protected] deduped
โ”‚ โ”œโ”€โ”ฌ @typescript-eslint/[email protected]
โ”œโ”€โ”€ [email protected]

Switch: create all cases - doesnt work for dynamic union type

Describe the bug

I have dynamic union type as type Animal = "cat" | "dog" | "rabbit" | "snake" coming from string literal type of array values and I don't see the option Create all cases

How to reproduce

try to use the following code :

export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;

const animals = tuple('cat', 'dog', 'rabbit', 'snake');
type Animal = (typeof animals)[number];  // union type

function getAnimalInfo(value: Animal): string {
  switch (value) {
  }
}

Expected behavior

Successfully creates a case for each member of the union type like

function getAnimalInfo(value: Animal): string {
  switch (value) {
    case 'cat':
      return 'Here is some info';
    case 'dog':
      return 'Here is some info';
    case 'rabbit':
      return 'Here is some info';
    case 'snake':
      return 'Here is some info';
    default:
      return '';
  }
}

Screenshots

Screenshot 2021-07-07 at 13 47 07

Additional information

  • Version of the extension impacted: v1.7.0

Convert a `let` to `const` for a variable declaration where the context allows it

Is this request related to a problem? Please describe.

Favouring immutability, it would be good to have a quick fix to convert a variable declaration from let to const if the scope and usage of the variable allows it.

Describe the solution you'd like

Given the following code:

function getValue(): string {
   let someVariable = 'value';
   return someVariable;
}

A quick-fix on someVariable would allow conversion to this:

function getValue(): string {
   const someVariable = 'value';
   return someVariable;
}

Whereas it wouldn't be available for:

function getValue(): string {
   let someVariable = 'value';
   someVariable = 'anotherValue';
   return someVariable;
}

Creating variable from JSX Attributes fails

Describe the bug

Creating a variable from an Identifier in a JSX attribute node generates invalid code.

How to reproduce

Consider

function MyButton() {
  return <button onClick={handleClick} />
}

Put the cursor on handleClick. Select "Create Variable handleClick" option.

Generated code is broken:

function MyButton() {
  return <button onClick={const handleClick = ;
  handleClick} />
}

Expected behavior

The variable declaration should be at the correct position.

function MyButton() {
  const handleClick = |;
  return <button onClick={handleClick} />
}

Additional information

  • Version of the extension impacted: v1.1.0

Switch: create all cases - comments from enum are inserted mid-through generated cases

Describe the bug

When using quick fix: create all cases for switch with enum variable, which enum had comments between members, comments from enum are inserted mid-through generated switch cases (screenshot).

How to reproduce

  1. Create an enum that has comments inside
  2. Use create all cases for switch

Expected behavior

Comments are omitted, and if not, then they at least shouldn't be inserted mid-case (screenshot)

Screenshots

2020-11-29_00h05_39

Additional information

  • Version of the extension impacted: v1.7.0

I have a lot of other extensions installed, but now I don't have the time to disable them all and try to reproduce this again.

Use underlying type instead of narrowed literals for type inferrance

Describe what's missing

As of version 1.4 the extension adds the inferred type to function parameters when using the Create Function action in typescript files. When the argument is a literal though like 3 (number) or "Hi" (string) it will generate the parameter declaration using this narrowed type instead of the general type (number or string).
I suggest to substitute the narrowed type with the general type in the cases of primitive literals (in particular string and enums).

How would it work

When analysing the argument types, the extension could special-case arguments of type NumericLiteral and StringLiteral and use number or string instead of the types received from the type checker.

Expected behavior

Instead of doSomething("hello") -> function doSomething(param1: "hello") we'd get function doSomething(param1: string).

Additional information

  • Version of the extension used: v1.4

Rationale

I'm thinking of use cases like this:

logError("Oops, something went wrong");

or

throw new TotallyNonExistingError("I'm sorry Dave");

(last use case would be Create Class, but it's not using the types yet). Surely here the general string type would be more appropriate than the narrowed one.

Add extension to Open VSX Registry

Describe what's missing

The extension can't be found in Open VSX Registry

How would it work

The extension would be available in Open VSX Registry (same as the Abracadabra one by the same author).

Switch: create all cases - doen't work when enum is exported

Describe the bug

Option Create all cases for switch statements does not seem to work when switch variable is typed with enum that has keyword export before enum. It creates an empty switch.

How to reproduce

  1. Create an enum that is a named export (export enum Test { ... })
  2. Try to use quick fix: create all cases on a switch with variable typed with that enum

Expected behavior

Successfully creates a case for each member of the enum in question

Screenshots

2020-11-29_00h03_30

Additional information

  • Version of the extension impacted: v1.7.0

I have a lot of other extensions installed, but now I don't have the time to disable them all and try to reproduce this again.

Quick-fix to create a class from its call expression

Is this request related to a problem? Please describe.

Create a class declaration from its call expression using a quick-fix.

Describe the solution you'd like

Similarly to the create function feature, it's nice, especially when writing test-first, to be able to write some code that described how you'd like to create a new class with its dependencies that will be injected via the constructor.

An example could be:

const aString: string = "test";
const aNumber: number = 1;

new MyClass(aString, aNumber);

Then a quick-fix from MyClass would generate a class such as:

class MyClass {
   constructor(private readonly aString: string, private readonly aNumber: number) {
     this.aString = aString;
     this.aNumber = aNumber;
  }
}

Additional context

Coming from a Java background using the JetBrains IntelliJ (with similar support as WebStorm) it's really easy to just quick-fix to generate the necessary code.

Type inference does not find imported type

Describe the bug

When I perform the "Create function" with types action an argument that is declared as a type that was imported the parameter of the generated function will be any:

// hocusPocusMyType.ts
export type MyType = {
	aNumber: number;
};
// hocuspocustest.ts
import { MyType } from "./hocusPocusMyType";

function bla() {
	const c: MyType = { aNumber: 3 };
	doSomething(c);
}

->

function doSomething(c: any) {
  // Implement
}

How to reproduce

Use the code above, any imported type should repro this issue.

Expected behavior

The generated function signature will include the actual type instead of any.

Additional information

The action behaves correctly if the type is declared within the same module.

  • Version of the extension impacted: v1.4.0

Create a function from Identifier in JSX attribute

Is this request related to a problem? Please describe.

Consider

function MyButton() {
  return <button onClick={handleClick} />
}

We can't create a function declaration from handleClick. Only a variable.

Describe the solution you'd like

With the cursor on handleClick, it's very likely we want to create a function declaration instead of a variable.

That's true because it's a parameter of some sort, so a variable or a function declaration would both be valid.

At least, it should work for Identifiers in JSX Attributes. Ideally, we should handle Identifiers passed as params and propose to create both a variable or a function to the end user.

Additional context

Suggested in nicoespeon/abracadabra#64

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.