microsoft / microsoft/TypeScript

Add `async`ness to semantic highlighting

Open
#57,593 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
1d 19h
Merged PRs (30d)
117

Description

🔍 Search Terms

"expose type syntax highlight", "semantic syntax highlighting for promise", "highlight variables based on type"

✅ Viability Checklist
⭐ Suggestion

Expose (some) type information to the syntax highlighter for semantic styling so we can highlight variables / function calls of particular types.

📃 Motivating Example

Hungarian notation has long since marked as something to be avoided, yet a common practice I see is naming async functions with an Async suffix, or with an await prefix.

fs.readFile();
await fs.readFileAsync();

await awaitMyFunction();

This indicates that whether or not something returns a promise is important enough that we're marking async functions with these prefixes/suffixes.

Hungarian notation went away because IDE's improved and we could start to rely on it to give us type information (on hover) and via type checking.

While researching this I stumbled upon the semantic highlighting config in VSCode and decided to take a leaf out of rusts book which underlines mut values and tried to apply an underline to any variable T where T extends Thenable<any>.

However the best I could get was to mark functions tagged as async as this is the only information available to the syntax highlighter (as seen by running the "Developer: Inspect Editor Tokens and Scopes" command)

	"editor.semanticTokenColorCustomizations": {
		"[Default Dark Modern]": {
			"rules": {
				"*.async": {
					"underline": true,
				},
			},
		}
	},

But this falls over in a few places

interface Foo {
  doThing(): Promise<string>;
}

class Bar extends Foo {
  async doThing() { // <- underlines correctly here
    return 'hi';
  }
}

const bar = new Bar();
bar.doThing(); // <- and here

const barAsFoo: Foo = bar;

barAsFoo.doThing(); // <- no underline here.

It also doesn't do anything for thenable valued variables

const prom = bar.doThing(); // <- prom is not underlined

console.log('doing something else");

await prom;

image

In my head, the ideal situation is that a textmate modifier is added to any variable whose value (or method whose return type) exclusively extends Promise (or Thenable). That way prom would be underlined.

I understand there will be some complexities and many edge cases for figuring this out; its not necessarily true that Promise refers to a promise

type Promise<TAction extends string = string> = `I promise I will ${TAction}`;

function getActionFromPromise(prom: Promise) {
  const match = /^I promise I will (.*)$/.exec(prom);

  return match[1];
}

console.log(getActionFromPromise('I promise I will not write esoteric code'));

or

function getUserData(): Promise<User> | null {
  if (!db.isConnected()) return null;

  return db.getUser(ctx.currentUserId);
}

also

function doNothing<T>(val: T): T {
  return val;
}

const foo = doNothing(Promise.resolve());

There may be ways around these problems (maybe something like T extends Promise<any> ? Promise<any> extends T ? true : false : false)

💻 Use Cases
  1. What do you want to use this for? As mentioned in "motivating example"
  2. What shortcomings exist with current approaches? ' '
  3. What workarounds are you using in the meantime? ' '

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with TypeScript's semantic highlighting behavior and the VS Code semantic highlighting configuration described in the issue, using Developer: Inspect Editor Tokens and Scopes to compare existing async tokens. Determine the supported semantics for promise- or thenable-valued variables and methods, including the listed type and union edge cases; done requires an agreed design and corresponding semantic highlighting behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.