TypeScript Go (TypeScript 7)

repository·main·Indexed 12 days ago

https://github.com/microsoft/typescript-go

A native implementation of the TypeScript language service providing high-performance IDE features such as completions, diagnostics, and go-to-definition. Includes the tsgo command as a drop-in replacement for tsc, a native preview extension for VS Code, and internal Go-based filesystem watching via fswatch.

Tokens
29.4K
Snippets
93
Records
144
Agent score
95%

What's inside TypeScript Go

  1. How Glob Patterns are Compiled

    main

    Glob patterns are transformed from a raw Spec into a Pattern via the COMPILE_PATTERN process.

    1. Normalization: The spec is resolved against a basePath into absolute path components.
    2. Implicit Globbing: If the last component of the normalized path does not contain ., *, or ?, the algorithm treats it as an implicit glob by appending ** and * to the components.
    3. Component Classification:
      • ** becomes a DoubleAsterisk component.
      • Components without * or ? become Literal components.
      • Components with * or ? become Wildcard components, which are further parsed into SegLiteral, SegStar, or SegQuestion segments.

    Note: If the last element of the normalized components is ** and the usage mode is not Exclude, compilation will fail.

  2. Understand the Microsoft Support Policy

    main

    TypeScript support and servicing depend on how the project is being consumed:

    • Standard Releases: TypeScript releases include new features and fixes (security and non-security). Critical issues may be addressed via servicing updates to the latest release.
    • Microsoft Products: When bundled with a Microsoft product, support follows the Modern Support Policy.
    • Visual Studio: For versions of Visual Studio that are in 'under-support' releases, servicing is limited to security fixes only.
    • Community Support: Limited to GitHub issues, Stack Overflow, and Discord.
    • Assisted Support: Professional support is available via the Microsoft assisted support team.
  3. Understand `.min.js` default exclusion

    main

    The glob matching algorithm includes a default exclusion rule for .min.js files to prevent them from being matched by default in certain scenarios.

    Rules for exclusion:

    • The exclusion only applies when the pattern's usage mode is set to Files.
    • It only applies to wildcard components.
    • A file is excluded if:
      1. Its filename ends with the .min.js suffix (case-sensitivity depends on the pattern configuration).
      2. OR the pattern itself explicitly mentions the .min.js or .min. suffix within its literal segments.

    If the pattern is not in Files mode, or if the file/pattern does not meet the suffix criteria, the exclusion does not apply.

  4. Understand the internal formatting lifecycle

    main

    The internal formatting process follows this lifecycle:

    1. Initialization: Most APIs use Format* methods to configure a FormatSpan, which defines the specific range of the SourceFile to be formatted.
    2. Scanning: A scanner (with or without JSX support) identifies the highest-level node covering the span and recurses through its children.
    3. Indentation: As the scanner recurses, processNode is called on children to determine and pass down indentation levels.
    4. Rule Application: The core logic resides in processPair, which compares the current node with the previous node. This method mutates the formatting context and uses createRulesMap to fetch a set of rules.
    5. Rule Execution: Formatting decisions are driven by rules (defined in rules.ts) that reference node pairs or token ranges to determine which actions to apply.
  5. Understand Glob Matching Algorithm Concepts

    main

    The glob matching logic follows a formal specification to ensure consistent file-path matching. Key concepts include:

    • Path: A normalized, /-separated absolute file path (e.g., /project/src/index.ts).
    • Path component: A single segment between / delimiters. The root component is an empty string "".
    • Spec: The raw user-provided glob string (e.g., src/**/*.ts).
    • Pattern: The compiled version of a spec, containing a list of components, a usage mode, and a case-sensitivity flag.
    • Usage Modes:
      • Files: Matches complete file paths.
      • Directories: Matches directory prefixes for traversal pruning.
      • Exclude: Matches paths to be excluded.
    • Component Kinds:
      • Literal: No * or ? characters.
      • Wildcard: Contains * or ? characters.
      • DoubleAsterisk: The exact string **.
    • Segment Kinds (within a Wildcard component):
      • SegLiteral: An exact literal substring.
      • SegStar: Matches zero or more characters excluding /.
      • SegQuestion: Matches exactly one character excluding /.
  6. Select a specific filesystem watcher

    main

    While fswatch.Default() automatically selects the best watcher for the current OS, you can explicitly request a specific backend. All watchers are available on every platform, but they may not be supported by the underlying kernel.

    To check if a watcher is supported at runtime, use fswatch.Available(). If you attempt to use an unsupported watcher, WatchDirectory will return fswatch.ErrUnavailable.

    Supported watchers by OS:

    • linux: fanotify (default, kernel ≥ 5.13), inotify
    • darwin: FSEvents (default), kqueue
    • windows: ReadDirectoryChangesW
    • freebsd, openbsd, netbsd, dragonfly: kqueue
    // Example of using a specific watcher with options
    sub, err := fswatch.Inotify().WatchDirectory(dir, callback, fswatch.WithRecursive())
  7. How TypeScript formatting works

    main

    TypeScript formatting requires two primary components: a SourceFile representing the code and a formatting context containing user settings (such as tab size and newline character).

    The output of the formatting process is a collection of TextChange objects. Each TextChange object contains the new string content and the specific text it is intended to replace.

  8. Rules for Wildcard and Double Asterisk Matching

    main

    The matching algorithm applies specific constraints during traversal and wildcard evaluation:

    • Hidden Paths: If a component starts with . (e.g., .gitignore), it is considered a hidden path. If a DoubleAsterisk or a Wildcard (starting with * or ?) attempts to match a hidden path, the match will fail (unless in Exclude mode).
    • Package Folders: Components matching node_modules, bower_components, or jspm_packages (case-insensitive) are treated as package folders. If a DoubleAsterisk or a Wildcard component encounters a package folder, the match is rejected (unless in Exclude mode).
    • Double Asterisk (**): This component allows for matching across multiple directory levels. It attempts to skip segments to find a valid match for the subsequent pattern components.
  9. Understand fswatch event behavior

    main

    When consuming events from fswatch, be aware of the following behaviors:

    1. Batching: Events arriving in quick succession are batched together before being delivered to the callback.
    2. Ordering: The order of events within a single batch is not guaranteed.
    3. Paths: All paths in events are absolute. Because backends report canonical paths, always resolve symlinks before subscribing using filepath.EvalSymlinks to ensure consistency.
  10. Algorithm Invariants and Constraints

    main

    When implementing or using the glob matching algorithm, be aware of these core invariants:

    • Invalid Patterns: Any include or directory spec ending in ** will cause COMPILE_PATTERN to return failure.
    • Pattern Exhaustion: If a pattern is exhausted but path components remain, exclude patterns return true and all other patterns return false.
    • Complexity: MATCH_SEGMENTS is guaranteed to be $O(n imes m)$, where $n$ is string length and $m$ is segment count.
    • Precedence: Excludes are always evaluated before includes.
    • Wildcard Behavior:
      • For include patterns, ** does not descend into hidden paths or package folders.
      • A wildcard component whose first segment is a star (*) or question mark (?) will not match hidden path components.
      • For include patterns, wildcard components reject package folders, while literal components do not.
    • Symlinks: Symlink cycles are detected via canonical paths and the directory is skipped.
  11. Use fswatch to monitor filesystem changes

    main

    To monitor a directory for changes, use fswatch.Default().WatchDirectory(path, callback). The callback receives a slice of fswatch.Event objects and an error. Each event contains a Kind and an absolute Path.

    Note that the callback runs on a library goroutine and is serialized for each watch, meaning the same watch's callback will never run concurrently with itself. Because backends report canonical paths, you should resolve symlinks using filepath.EvalSymlinks before subscribing to ensure the path matches your expectations.

    package main
    
    import (
    	"fmt"
    	"log"
    	"os"
    	"os/signal"
    
    	"github.com/microsoft/typescript-go/internal/fswatch"
    )
    
    func main() {
    	dir, _ := os.Getwd()
    
    	sub, err := fswatch.Default().WatchDirectory(dir, func(events []fswatch.Event, err error) {
    		if err != nil {
    			log.Println("watch error:", err)
    			return
    		}
    		for _, e := range events {
    			fmt.Printf("%s %s\n", e.Kind, e.Path)
    		}
    	})
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer sub.Close()
    
    	c := make(chan os.Signal, 1)
    	signal.Notify(c, os.Interrupt)
    	<-c
    }