Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax uppercase check for types qualified with a namespace #1493

Merged
merged 3 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bumped GRPC message sizes to 1G (#1480)
- Fix format of ITF trace emitted by `verify` command (#1448)
- Relax uppercase check for types qualified with a namespace (#1494)

### Security

Expand Down Expand Up @@ -148,7 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- The latest supported node version is now bounded at <= 20, which covers the
latest LTS. (#1380)
- Shadowing names are now supported, which means that the same name can be redefined
- Shadowing names are now supported, which means that the same name can be redefined
in nested scopes. (#1394)
- The canonical unit type is now the empty tuple, `()`, rather than the empty
record, `{}`. This should only affect invisible things to do with sum type
Expand Down
18 changes: 12 additions & 6 deletions quint/src/parsing/ToIrListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,7 @@ export class ToIrListener implements QuintListener {
const name = ctx.qualId()!.text
const id = this.getId(ctx)

if (name[0].match('[a-z]')) {
this.errors.push(lowercaseTypeError(id, name))
}
this.checkForUppercaseTypeName(id, name)

const def: QuintTypeDef = {
id,
Expand All @@ -319,9 +317,8 @@ export class ToIrListener implements QuintListener {
const type = this.popType().unwrap(() =>
fail('internal error: type alias declaration parsed with no right hand side')
)
if (name[0].match('[a-z]')) {
this.errors.push(lowercaseTypeError(id, name))
}

this.checkForUppercaseTypeName(id, name)

let defWithoutParams: QuintTypeDef = { id: id, kind: 'typedef', name, type }
const def: QuintTypeDef =
Expand Down Expand Up @@ -1297,6 +1294,15 @@ export class ToIrListener implements QuintListener {
}
}
}

private checkForUppercaseTypeName(id: bigint, qualifiedName: string) {
const parts = qualifiedName.split('::')
const unqualifiedName = parts.pop()!

if (unqualifiedName[0].match('[a-z]')) {
this.errors.push(lowercaseTypeError(id, unqualifiedName, parts))
}
}
}

function popMany<T>(stack: T[], n: number, defaultGen: () => T): T[] {
Expand Down
22 changes: 12 additions & 10 deletions quint/src/parsing/parseErrors.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { QuintError } from '../quintError'

export function lowercaseTypeError(id: bigint, name: string): QuintError {
export function lowercaseTypeError(id: bigint, name: string, prefix: string[]): QuintError {
const original = [...prefix, name].join('::')
const newName = name[0].toUpperCase() + name.slice(1)
const replacement = [...prefix, newName].join('::')

return {
code: 'QNT007',
message: 'type names must start with an uppercase letter',
reference: id,
data: name[0].match('[a-z]')
? {
fix: {
kind: 'replace',
original: `type ${name[0]}`,
replacement: `type ${name[0].toUpperCase()}`,
},
}
: {},
data: {
fix: {
kind: 'replace',
original: `type ${original}`,
replacement: `type ${replacement}`,
},
romac marked this conversation as resolved.
Show resolved Hide resolved
},
}
}

Expand Down
2 changes: 1 addition & 1 deletion quint/testFixture/SuperSpec.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion quint/testFixture/SuperSpec.map.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions quint/testFixture/SuperSpec.qnt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ module withConsts {
const MyRecord: { i: int, b: bool, s: str }
const MyRecordWithComma: { i: int, b: bool, s: str, }

// A type prefixed with a namespace
type some::namespace::MyType = int

// a disjoint union is a common pattern in TLA+
type MyUnionType =
| Circle(int)
Expand Down
Loading