Skip to content

Commit

Permalink
Squashed 'packages/TestItemDetection/' content from commit 2c59c96
Browse files Browse the repository at this point in the history
git-subtree-dir: packages/TestItemDetection
git-subtree-split: 2c59c96cf62ab84bbaf9f94364fe0fb6c9a34979
  • Loading branch information
davidanthoff committed Jan 17, 2023
0 parents commit 42850af
Show file tree
Hide file tree
Showing 15 changed files with 605 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/jlpkgbutler-butler-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Run the Julia Package Butler

on:
push:
branches:
- main
- master
schedule:
- cron: '0 */1 * * *'
workflow_dispatch:

jobs:
butler:
name: "Run Package Butler"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: davidanthoff/julia-pkgbutler@releases/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
ssh-private-key: ${{ secrets.JLPKGBUTLER_TOKEN }}
channel: stable
40 changes: 40 additions & 0 deletions .github/workflows/jlpkgbutler-ci-master-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Run CI on main

on:
push:
branches:
- main
- master
workflow_dispatch:

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: ['1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8']
julia-arch: [x64, x86]
os: [ubuntu-latest, windows-latest, macOS-latest]
exclude:
- os: macOS-latest
julia-arch: x86

steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/julia-buildpkg@v1
env:
PYTHON: ""
- uses: julia-actions/julia-runtest@v1
env:
PYTHON: ""
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
files: ./lcov.info
flags: unittests
token: ${{ secrets.CODECOV_TOKEN }}

36 changes: 36 additions & 0 deletions .github/workflows/jlpkgbutler-ci-pr-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Run CI on PR

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: ['1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8']
julia-arch: [x64, x86]
os: [ubuntu-latest, windows-latest, macOS-latest]
exclude:
- os: macOS-latest
julia-arch: x86

steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/julia-buildpkg@v1
env:
PYTHON: ""
- uses: julia-actions/julia-runtest@v1
env:
PYTHON: ""
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
files: ./lcov.info
flags: unittests
token: ${{ secrets.CODECOV_TOKEN }}
23 changes: 23 additions & 0 deletions .github/workflows/jlpkgbutler-codeformat-pr-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Code Formatting

on:
push:
branches:
- main
- master
workflow_dispatch:

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: julia-actions/julia-codeformat@releases/v1
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Format files using DocumentFormat
title: '[AUTO] Format files using DocumentFormat'
body: '[DocumentFormat.jl](https://github.com/julia-vscode/DocumentFormat.jl) would suggest these formatting changes'
labels: no changelog
20 changes: 20 additions & 0 deletions .github/workflows/jlpkgbutler-compathelper-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run CompatHelper

on:
schedule:
- cron: '00 * * * *'
issues:
types: [opened, reopened]
workflow_dispatch:

jobs:
CompatHelper:
name: "Run CompatHelper.jl"
runs-on: ubuntu-latest
steps:
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: julia -e 'using CompatHelper; CompatHelper.main()'
17 changes: 17 additions & 0 deletions .github/workflows/jlpkgbutler-tagbot-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:

jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.JLPKGBUTLER_TOKEN }}
branches: true
1 change: 1 addition & 0 deletions .jlpkgbutler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
template = "bach"
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) 2022 David Anthoff

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.
18 changes: 18 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name = "TestItemDetection"
uuid = "76b0de8b-5c4b-48ef-a724-914b33ca988d"
authors = ["David Anthoff <anthoff@berkeley.edu>"]
version = "0.2.1-DEV"

[deps]
CSTParser = "00ebfdb7-1f24-5e51-bd34-a7502290713f"

[extras]
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[compat]
julia = "1"
CSTParser = "3"

[targets]
test = ["Test", "TestItemRunner"]
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TestItemDetection.jl

## Overview

This package provides low level features that are used by TestItemRunner.jl and LanguageServer.jl.
8 changes: 8 additions & 0 deletions src/TestItemDetection.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module TestItemDetection

import CSTParser
using CSTParser: EXPR

include("packagedef.jl")

end
149 changes: 149 additions & 0 deletions src/packagedef.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
include("vendored_code.jl")

function find_test_detail!(node, testitems, testsetups, errors)
node isa EXPR || return

if node.head == :macrocall && length(node.args)>0 && CSTParser.valof(node.args[1]) == "@testitem"
pos = 1 + get_file_loc(node)[2]
range = pos:pos+node.span-1

# filter out line nodes
child_nodes = filter(i->!(isa(i, EXPR) && i.head==:NOTHING && i.args===nothing), node.args)

# Check for various syntax errors
if length(child_nodes)==1
push!(errors, (error="Your @testitem is missing a name and code block.", range=range))
return
elseif length(child_nodes)>1 && !(child_nodes[2] isa EXPR && child_nodes[2].head==:STRING)
push!(errors, (error="Your @testitem must have a first argument that is of type String for the name.", range=range))
return
elseif length(child_nodes)==2
push!(errors, (error="Your @testitem is missing a code block argument.", range=range))
return
elseif !(child_nodes[end] isa EXPR && child_nodes[end].head==:block)
push!(errors, (error="The final argument of a @testitem must be a begin end block.", range=range))
return
else
option_tags = nothing
option_default_imports = nothing
option_setup = nothing

# Now check our keyword args
for i in child_nodes[3:end-1]
if !(i isa EXPR && i.head isa EXPR && i.head.head==:OPERATOR && CSTParser.valof(i.head)=="=")
push!(errors, (error="The arguments to a @testitem must be in keyword format.", range=range))
return
elseif !(length(i.args)==2)
error("This code path should not be possible.")
elseif CSTParser.valof(i.args[1])=="tags"
if option_tags!==nothing
push!(errors, (error="The keyword argument tags cannot be specified more than once.", range=range))
return
end

if !(i.args[2].head == :vect)
push!(errors, (error="The keyword argument tags only accepts a vector of symbols.", range=range))
return
end

option_tags = Symbol[]

for j in i.args[2].args
if !(j isa EXPR && j.head==:quotenode && length(j.args)==1 && j.args[1] isa EXPR && j.args[1].head==:IDENTIFIER)
push!(errors, (error="The keyword argument tags only accepts a vector of symbols.", range=range))
return
end

push!(option_tags, Symbol(CSTParser.valof(j.args[1])))
end
elseif CSTParser.valof(i.args[1])=="default_imports"
if option_default_imports!==nothing
push!(errors, (error="The keyword argument default_imports cannot be specified more than once.", range=range))
return
end

if !(CSTParser.valof(i.args[2]) in ("true", "false"))
push!(errors, (error="The keyword argument default_imports only accepts bool values.", range=range))
return
end

option_default_imports = parse(Bool, CSTParser.valof(i.args[2]))
elseif CSTParser.valof(i.args[1])=="setup"
if option_setup!==nothing
push!(errors, (error="The keyword argument setup cannot be specified more than once.", range=range))
return
end

if !(i.args[2].head == :vect)
push!(errors, (error="The keyword argument `setup` only accepts a vector of `@testsetup` names.", range=range))
return
end
option_setup = Symbol[]

for j in i.args[2].args
if !(j isa EXPR && j.head==:IDENTIFIER)
push!(errors, (error="The keyword argument `setup` only accepts a vector of `@testsetup` names.", range=range))
return
end

push!(option_setup, Symbol(CSTParser.valof(j)))
end
else
push!(errors, (error="Unknown keyword argument.", range=range))
return
end
end

if option_tags===nothing
option_tags = Symbol[]
end

if option_default_imports===nothing
option_default_imports = true
end

if option_setup===nothing
option_setup = Symbol[]
end

# TODO + 1 here is from the space before the begin end block. We might have to detect that,
# not sure whether that is always assigned to the begin end block EXPR
code_pos = get_file_loc(child_nodes[end])[2] + 1 + length("begin")

code_range = code_pos:code_pos+child_nodes[end].span - 1 - length("begin") - length("end")

push!(testitems, (name=CSTParser.valof(node.args[3]), range=range, code_range=code_range, option_default_imports=option_default_imports, option_tags=option_tags, option_setup=option_setup))
end
elseif node.head == :macrocall && length(node.args)>0 && CSTParser.valof(node.args[1]) == "@testsetup"
pos = 1 + get_file_loc(node)[2]
range = pos:pos+node.span-1

# filter out line nodes
child_nodes = filter(i->!(isa(i, EXPR) && i.head==:NOTHING && i.args===nothing), node.args)

# Check for various syntax errors
if length(child_nodes)==1
push!(errors, (error="Your @testsetup is missing a name and code block.", range=range))
return
elseif length(child_nodes)>1 && !(child_nodes[2] isa EXPR && child_nodes[2].head==:IDENTIFIER)
push!(errors, (error="Your @testsetup must have a first argument that is a valid identifier for the name.", range=range))
return
elseif length(child_nodes)==2
push!(errors, (error="Your @testsetup is missing a code block argument.", range=range))
return
elseif !(child_nodes[end] isa EXPR && child_nodes[end].head==:block)
push!(errors, (error="The final argument of a @testsetup must be a begin end block.", range=range))
return
else
# TODO + 1 here is from the space before the begin end block. We might have to detect that,
# not sure whether that is always assigned to the begin end block EXPR
code_pos = get_file_loc(child_nodes[end])[2] + 1 + length("begin")
code_range = code_pos:code_pos+child_nodes[end].span - 1 - length("begin") - length("end")
push!(testsetups, (name=CSTParser.valof(node.args[3]), range=range, code_range=code_range))
end
elseif node.head == :module && length(node.args)>=3 && node.args[3] isa EXPR && node.args[3].head==:block
for i in node.args[3].args
find_test_detail!(i, testitems, testsetups, errors)
end
end
end
Loading

0 comments on commit 42850af

Please sign in to comment.