Skip to content

Commit

Permalink
feat: Initial implementation, focused on parsing type definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
armsnyder committed Jul 1, 2024
1 parent 756e65e commit c25755d
Show file tree
Hide file tree
Showing 40 changed files with 3,414 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
17 changes: 17 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/dependabot-2.0.json
version: 2
updates:
- directory: /
package-ecosystem: gomod
schedule:
interval: monthly
commit-message:
prefix: chore
include: scope
- directory: /
package-ecosystem: github-actions
schedule:
interval: monthly
commit-message:
prefix: chore
include: scope
10 changes: 10 additions & 0 deletions .github/release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"packages": {
".": {
"release-type": "go",
"bump-minor-pre-major": true,
"include-v-in-tag": true
}
}
}
42 changes: 42 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow

on:
push:
branches:
- main
pull_request: {}
workflow_dispatch: {}

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ["1.20", "1.21", "1.22"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- run: go test -cover ./...

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: golangci/golangci-lint-action@v6
with:
version: v1.59.1

release-please:
runs-on: ubuntu-latest
needs: [test, lint]
if: github.ref == 'refs/heads/main'
steps:
- uses: googleapis/release-please-action@v4
id: release-please
with:
token: ${{ secrets.PAT }}
config-file: .github/release-please-config.json
manifest-file: .github/.release-please-manifest.json
120 changes: 120 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# See https://golangci-lint.run/usage/configuration/

linters:
disable-all: true
enable:
# See https://golangci-lint.run/usage/linters/
- asasalint # Check for pass []any as any in variadic func(...any).
- bodyclose # Checks whether HTTP response body is closed successfully.
- contextcheck # Check whether the function uses a non-inherited context.
- durationcheck # Check for two durations multiplied together.
- errcheck # Checks whether Rows.Err of rows is checked successfully.
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted.
- errorlint # Errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
- forbidigo # Forbids identifiers.
- gci # Gci controls Go package import order and makes it always deterministic.
- gocritic # Provides diagnostics that check for bugs, performance and style issues. Extensible without recompilation through dynamic rules. Dynamic rules are written declaratively with AST patterns, filters, report message and optional suggestion.
- godot # Check if comments end in a period.
- gosec # Inspects source code for security problems.
- gosimple # Linter for Go source code that specializes in simplifying code.
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string.
- inamedparam # Reports interfaces with unnamed method parameters.
- ineffassign # Detects when assignments to existing variables are not used.
- mirror # Reports wrong mirror patterns of bytes/strings usage.
- misspell # Finds commonly misspelled English words.
- musttag # Enforce field tags in (un)marshaled structs.
- nilerr # Finds the code that returns nil even if it checks that the error is not nil.
- nilnil # Checks that there is no simultaneous return of nil error and an invalid value.
- noctx # Finds sending http request without context.Context.
- nolintlint # Reports ill-formed or insufficient nolint directives.
- nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL.
- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative.
- protogetter # Reports direct reads from proto message fields when getters should be used.
- reassign # Checks that package variables are not reassigned.
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
- staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint.
- tenv # # Tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17.
- unconvert # Remove unnecessary type conversions.
- unused # Checks Go code for unused constants, variables, functions and types.

linters-settings:
# See https://golangci-lint.run/usage/linters/#linters-configuration
forbidigo:
forbid:
- 'fmt\.Print.*' # Should be using a logger
gci:
sections:
- standard
- default
- prefix(github.com/armsnyder)
gocritic:
enabled-tags:
- performance
- opinionated
- experimental
disabled-checks:
- whyNoLint # False positives, use nolintlint instead
govet:
enable-all: true
disable:
- fieldalignment # Too struct
nolintlint:
require-specific: true
revive:
enable-all-rules: true
rules:
# See https://revive.run/r
- name: add-constant # too strict
disabled: true
- name: argument-limit # too strict
disabled: true
- name: cognitive-complexity
arguments:
- 30
- name: cyclomatic
arguments:
- 30
- name: file-header # too strict
disabled: true
- name: function-length
arguments:
- 50 # statements
- 0 # lines (0 to disable)
- name: function-result-limit # too strict
disabled: true
- name: import-shadowing # too strict, results in uglier code
disabled: true
- name: line-length-limit # too strict
disabled: true
- name: max-public-structs # too strict
disabled: true
- name: modifies-parameter # too strict
disabled: true
- name: modifies-value-receiver # too strict
disabled: true
- name: nested-structs # too strict
disabled: true
- name: package-comments # too strict
disabled: true
- name: unhandled-error
disabled: true # not as good as errcheck

issues:
exclude-rules:
- path: _test\.go$
linters:
- gosec # too strict
- noctx # too strict
- path: _test\.go$
text: (cognitive-complexity|function-length|dot-imports|import-alias-naming) # too strict
linters:
- revive
# Shadowing err is common.
- text: 'shadow: declaration of "err"'
linters:
- govet
- text: "^exported:.+stutters" # too strict and gets in the way of combining types like handlers
linters:
- revive
- path: _test\.go$
text: "unused-parameter" # too strict
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Adam Snyder

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# TypeScript AST

This library provides a way to parse TypeScript source code into an abstract
syntax tree (AST) in Golang. The packages are laid out similar to the standard
[go](https://pkg.go.dev/go) library.

[Package Documentation](https://pkg.go.dev/github.com/armsnyder/typescript-ast-go)

The main two packages are:

- [parser](https://pkg.go.dev/github.com/armsnyder/typescript-ast-go/parser):
Parse TypeScript source code into an AST.
- [ast](https://pkg.go.dev/github.com/armsnyder/typescript-ast-go/ast): The
AST nodes and visitor for TypeScript source code.

This library was originally created in order to parse TypeScript type
definitions specifically for the Language Server Protocol Specification. As a
result, it is not feature complete and may not work for all TypeScript source
code.
8 changes: 8 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package ast defines the abstract syntax tree (AST) for the TypeScript
// programming language and provides functionality for traversing the AST.
package ast

// Node is a common interface that all nodes in the AST implement.
type Node interface {
node()
}
138 changes: 138 additions & 0 deletions ast/expression.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package ast

import "github.com/armsnyder/typescript-ast-go/token"

// Expr is a [Node] that represents an expression. An expression produces a
// value.
type Expr interface {
Node
expr()
}

// NumericLiteral is a numeric literal expression.
type NumericLiteral struct {
Text string
}

func (n *NumericLiteral) String() string {
return n.Text
}

func (*NumericLiteral) node() {}
func (*NumericLiteral) expr() {}

// StringLiteral is a string literal expression.
type StringLiteral struct {
Text string
}

func (n *StringLiteral) String() string {
return n.Text
}

func (*StringLiteral) node() {}
func (*StringLiteral) expr() {}

// ArrayLiteralExpression is an array literal expression.
type ArrayLiteralExpression struct {
Elements []Expr
}

func (*ArrayLiteralExpression) node() {}
func (*ArrayLiteralExpression) expr() {}

// Identifier is an identifier literal expression.
type Identifier struct {
Text string
}

func (n *Identifier) String() string {
return n.Text
}

func (*Identifier) node() {}
func (*Identifier) expr() {}

// QualifiedName is a qualified name expression.
type QualifiedName struct {
Left *Identifier
Right *Identifier
}

func (*QualifiedName) node() {}
func (*QualifiedName) expr() {}

// EnumMember is an enum member expression.
type EnumMember struct {
Name *Identifier
Initializer Expr
LeadingComment string
}

func (n *EnumMember) String() string {
return n.LeadingComment
}

func (*EnumMember) node() {}
func (*EnumMember) expr() {}

// TypeParameter is a type parameter expression.
type TypeParameter struct {
Name *Identifier
}

func (*TypeParameter) node() {}
func (*TypeParameter) expr() {}

// HeritageClause is a heritage clause expression.
type HeritageClause struct {
Types []*ExpressionWithTypeArguments
}

func (*HeritageClause) node() {}
func (*HeritageClause) expr() {}

// ExpressionWithTypeArguments is an expression with type arguments.
type ExpressionWithTypeArguments struct {
Expression *Identifier
}

func (*ExpressionWithTypeArguments) node() {}
func (*ExpressionWithTypeArguments) expr() {}

// Parameter is a parameter expression.
type Parameter struct {
Name *Identifier
Type Type
}

func (*Parameter) node() {}
func (*Parameter) expr() {}

// VariableDeclarationList is an expression that declares a list of variables.
type VariableDeclarationList struct {
Declarations []*VariableDeclaration
}

func (*VariableDeclarationList) node() {}
func (*VariableDeclarationList) expr() {}

// VariableDeclaration is an expression that declares a variable.
type VariableDeclaration struct {
Name *Identifier
Type Type
Initializer Expr
}

func (*VariableDeclaration) node() {}
func (*VariableDeclaration) expr() {}

// PrefixUnaryExpression is an expression that applies a unary operator to an
// operand.
type PrefixUnaryExpression struct {
Operator token.Kind
Operand Expr
}

func (*PrefixUnaryExpression) node() {}
func (*PrefixUnaryExpression) expr() {}
Loading

0 comments on commit c25755d

Please sign in to comment.