Remove special pre-visit for module docstrings (#9261)

This ensures that we visit the module docstring like any other string.

Closes https://github.com/astral-sh/ruff/issues/9260.
This commit is contained in:
Charlie Marsh 2023-12-23 10:03:12 -05:00 committed by GitHub
parent 506ffade6c
commit 20def33fb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 306 additions and 227 deletions

View File

@ -0,0 +1,9 @@
import a
"""Some other docstring."""
import b
"""Some other docstring."""
import c

View File

@ -0,0 +1,5 @@
"""Docstring"""
"""Non-docstring"""
from __future__ import absolute_import

View File

@ -1,30 +1,28 @@
# These should change
x = u"Hello"
u"Hello"
u'world'
x = u"Hello" # UP025
print(u"Hello")
u'world' # UP025
print(u'world')
print(u"Hello") # UP025
print(u'world') # UP025
import foo
foo(u"Hello", U"world", a=u"Hello", b=u"world")
foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
# These should stay quoted they way they are
# Retain quotes when fixing.
x = u'hello' # UP025
x = u"""hello""" # UP025
x = u'''hello''' # UP025
x = u'Hello "World"' # UP025
x = u'hello'
x = u"""hello"""
x = u'''hello'''
x = u'Hello "World"'
# These should not change
u = "Hello"
u = u
u = "Hello" # OK
u = u # OK
def hello():
return"Hello"
return"Hello" # OK
f"foo"u"bar"
f"foo" u"bar"
f"foo"u"bar" # OK
f"foo" u"bar" # OK

View File

@ -287,7 +287,18 @@ where
// Track whether we've seen docstrings, non-imports, etc.
match stmt {
Stmt::Expr(ast::StmtExpr { value, .. })
if !self
.semantic
.flags
.intersects(SemanticModelFlags::MODULE_DOCSTRING)
&& value.is_string_literal_expr() =>
{
self.semantic.flags |= SemanticModelFlags::MODULE_DOCSTRING;
}
Stmt::ImportFrom(ast::StmtImportFrom { module, names, .. }) => {
self.semantic.flags |= SemanticModelFlags::MODULE_DOCSTRING;
// Allow __future__ imports until we see a non-__future__ import.
if let Some("__future__") = module.as_deref() {
if names
@ -301,9 +312,11 @@ where
}
}
Stmt::Import(_) => {
self.semantic.flags |= SemanticModelFlags::MODULE_DOCSTRING;
self.semantic.flags |= SemanticModelFlags::FUTURES_BOUNDARY;
}
_ => {
self.semantic.flags |= SemanticModelFlags::MODULE_DOCSTRING;
self.semantic.flags |= SemanticModelFlags::FUTURES_BOUNDARY;
if !(self.semantic.seen_import_boundary()
|| helpers::is_assignment_to_a_dunder(stmt)
@ -1435,11 +1448,8 @@ where
impl<'a> Checker<'a> {
/// Visit a [`Module`]. Returns `true` if the module contains a module-level docstring.
fn visit_module(&mut self, python_ast: &'a Suite) -> bool {
fn visit_module(&mut self, python_ast: &'a Suite) {
analyze::module(python_ast, self);
let docstring = docstrings::extraction::docstring_from(python_ast);
docstring.is_some()
}
/// Visit a list of [`Comprehension`] nodes, assumed to be the comprehensions that compose a
@ -2006,14 +2016,8 @@ pub(crate) fn check_ast(
);
checker.bind_builtins();
// Check for module docstring.
let python_ast = if checker.visit_module(python_ast) {
&python_ast[1..]
} else {
python_ast
};
// Iterate over the AST.
checker.visit_module(python_ast);
checker.visit_body(python_ast);
// Visit any deferred syntax nodes. Take care to visit in order, such that we avoid adding

View File

@ -35,7 +35,8 @@ mod tests {
#[test_case(Rule::LineTooLong, Path::new("E501_3.py"))]
#[test_case(Rule::MixedSpacesAndTabs, Path::new("E101.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E40.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_0.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_1.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.ipynb"))]
#[test_case(Rule::MultipleImportsOnOneLine, Path::new("E40.py"))]
#[test_case(Rule::MultipleStatementsOnOneLineColon, Path::new("E70.py"))]
@ -65,7 +66,7 @@ mod tests {
}
#[test_case(Rule::IsLiteral, Path::new("constant_literals.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.py"))]
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_0.py"))]
#[test_case(Rule::TypeComparison, Path::new("E721.py"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(

View File

@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
---
E402.py:25:1: E402 Module level import not at top of file
E402_0.py:25:1: E402 Module level import not at top of file
|
23 | sys.path.insert(0, "some/path")
24 |
@ -11,7 +11,7 @@ E402.py:25:1: E402 Module level import not at top of file
27 | import matplotlib
|
E402.py:27:1: E402 Module level import not at top of file
E402_0.py:27:1: E402 Module level import not at top of file
|
25 | import f
26 |
@ -21,7 +21,7 @@ E402.py:27:1: E402 Module level import not at top of file
29 | matplotlib.use("Agg")
|
E402.py:31:1: E402 Module level import not at top of file
E402_0.py:31:1: E402 Module level import not at top of file
|
29 | matplotlib.use("Agg")
30 |
@ -31,7 +31,7 @@ E402.py:31:1: E402 Module level import not at top of file
33 | __some__magic = 1
|
E402.py:35:1: E402 Module level import not at top of file
E402_0.py:35:1: E402 Module level import not at top of file
|
33 | __some__magic = 1
34 |
@ -39,7 +39,7 @@ E402.py:35:1: E402 Module level import not at top of file
| ^^^^^^^^ E402
|
E402.py:45:1: E402 Module level import not at top of file
E402_0.py:45:1: E402 Module level import not at top of file
|
43 | import j
44 |
@ -47,7 +47,7 @@ E402.py:45:1: E402 Module level import not at top of file
| ^^^^^^^^ E402
|
E402.py:45:11: E402 Module level import not at top of file
E402_0.py:45:11: E402 Module level import not at top of file
|
43 | import j
44 |

View File

@ -0,0 +1,22 @@
---
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
---
E402_1.py:5:1: E402 Module level import not at top of file
|
3 | """Some other docstring."""
4 |
5 | import b
| ^^^^^^^^ E402
6 |
7 | """Some other docstring."""
|
E402_1.py:9:1: E402 Module level import not at top of file
|
7 | """Some other docstring."""
8 |
9 | import c
| ^^^^^^^^ E402
|

View File

@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
---
E402.py:35:1: E402 Module level import not at top of file
E402_0.py:35:1: E402 Module level import not at top of file
|
33 | __some__magic = 1
34 |
@ -9,7 +9,7 @@ E402.py:35:1: E402 Module level import not at top of file
| ^^^^^^^^ E402
|
E402.py:45:1: E402 Module level import not at top of file
E402_0.py:45:1: E402 Module level import not at top of file
|
43 | import j
44 |
@ -17,7 +17,7 @@ E402.py:45:1: E402 Module level import not at top of file
| ^^^^^^^^ E402
|
E402.py:45:11: E402 Module level import not at top of file
E402_0.py:45:11: E402 Module level import not at top of file
|
43 | import j
44 |

View File

@ -55,7 +55,8 @@ mod tests {
#[test_case(Rule::UnusedImport, Path::new("F401_20.py"))]
#[test_case(Rule::ImportShadowedByLoopVar, Path::new("F402.py"))]
#[test_case(Rule::UndefinedLocalWithImportStar, Path::new("F403.py"))]
#[test_case(Rule::LateFutureImport, Path::new("F404.py"))]
#[test_case(Rule::LateFutureImport, Path::new("F404_0.py"))]
#[test_case(Rule::LateFutureImport, Path::new("F404_1.py"))]
#[test_case(Rule::UndefinedLocalWithImportStarUsage, Path::new("F405.py"))]
#[test_case(Rule::UndefinedLocalWithNestedImportStarUsage, Path::new("F406.py"))]
#[test_case(Rule::FutureFeatureNotDefined, Path::new("F407.py"))]

View File

@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
---
F404.py:6:1: F404 `from __future__` imports must occur at the beginning of the file
F404_0.py:6:1: F404 `from __future__` imports must occur at the beginning of the file
|
4 | from collections import namedtuple
5 |

View File

@ -0,0 +1,12 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
---
F404_1.py:5:1: F404 `from __future__` imports must occur at the beginning of the file
|
3 | """Non-docstring"""
4 |
5 | from __future__ import absolute_import
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ F404
|

View File

@ -1,284 +1,302 @@
---
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
---
UP025.py:2:5: UP025 [*] Remove unicode literals from strings
UP025.py:1:1: UP025 [*] Remove unicode literals from strings
|
1 | # These should change
2 | x = u"Hello"
| ^^^^^^^^ UP025
3 |
4 | u'world'
|
= help: Remove unicode prefix
Safe fix
1 1 | # These should change
2 |-x = u"Hello"
2 |+x = "Hello"
3 3 |
4 4 | u'world'
5 5 |
UP025.py:4:1: UP025 [*] Remove unicode literals from strings
|
2 | x = u"Hello"
3 |
4 | u'world'
1 | u"Hello"
| ^^^^^^^^ UP025
5 |
6 | print(u"Hello")
2 |
3 | x = u"Hello" # UP025
|
= help: Remove unicode prefix
Safe fix
1 1 | # These should change
2 2 | x = u"Hello"
3 3 |
4 |-u'world'
4 |+'world'
5 5 |
6 6 | print(u"Hello")
7 7 |
1 |-u"Hello"
1 |+"Hello"
2 2 |
3 3 | x = u"Hello" # UP025
4 4 |
UP025.py:6:7: UP025 [*] Remove unicode literals from strings
UP025.py:3:5: UP025 [*] Remove unicode literals from strings
|
4 | u'world'
5 |
6 | print(u"Hello")
1 | u"Hello"
2 |
3 | x = u"Hello" # UP025
| ^^^^^^^^ UP025
4 |
5 | u'world' # UP025
|
= help: Remove unicode prefix
Safe fix
1 1 | u"Hello"
2 2 |
3 |-x = u"Hello" # UP025
3 |+x = "Hello" # UP025
4 4 |
5 5 | u'world' # UP025
6 6 |
UP025.py:5:1: UP025 [*] Remove unicode literals from strings
|
3 | x = u"Hello" # UP025
4 |
5 | u'world' # UP025
| ^^^^^^^^ UP025
6 |
7 | print(u"Hello") # UP025
|
= help: Remove unicode prefix
Safe fix
2 2 |
3 3 | x = u"Hello" # UP025
4 4 |
5 |-u'world' # UP025
5 |+'world' # UP025
6 6 |
7 7 | print(u"Hello") # UP025
8 8 |
UP025.py:7:7: UP025 [*] Remove unicode literals from strings
|
5 | u'world' # UP025
6 |
7 | print(u"Hello") # UP025
| ^^^^^^^^ UP025
7 |
8 | print(u'world')
8 |
9 | print(u'world') # UP025
|
= help: Remove unicode prefix
Safe fix
3 3 |
4 4 | u'world'
5 5 |
6 |-print(u"Hello")
6 |+print("Hello")
7 7 |
8 8 | print(u'world')
9 9 |
4 4 |
5 5 | u'world' # UP025
6 6 |
7 |-print(u"Hello") # UP025
7 |+print("Hello") # UP025
8 8 |
9 9 | print(u'world') # UP025
10 10 |
UP025.py:8:7: UP025 [*] Remove unicode literals from strings
UP025.py:9:7: UP025 [*] Remove unicode literals from strings
|
6 | print(u"Hello")
7 |
8 | print(u'world')
7 | print(u"Hello") # UP025
8 |
9 | print(u'world') # UP025
| ^^^^^^^^ UP025
9 |
10 | import foo
10 |
11 | import foo
|
= help: Remove unicode prefix
Safe fix
5 5 |
6 6 | print(u"Hello")
7 7 |
8 |-print(u'world')
8 |+print('world')
9 9 |
10 10 | import foo
11 11 |
6 6 |
7 7 | print(u"Hello") # UP025
8 8 |
9 |-print(u'world') # UP025
9 |+print('world') # UP025
10 10 |
11 11 | import foo
12 12 |
UP025.py:12:5: UP025 [*] Remove unicode literals from strings
UP025.py:13:5: UP025 [*] Remove unicode literals from strings
|
10 | import foo
11 |
12 | foo(u"Hello", U"world", a=u"Hello", b=u"world")
11 | import foo
12 |
13 | foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
| ^^^^^^^^ UP025
13 |
14 | # These should stay quoted they way they are
14 |
15 | # Retain quotes when fixing.
|
= help: Remove unicode prefix
Safe fix
9 9 |
10 10 | import foo
11 11 |
12 |-foo(u"Hello", U"world", a=u"Hello", b=u"world")
12 |+foo("Hello", U"world", a=u"Hello", b=u"world")
13 13 |
14 14 | # These should stay quoted they way they are
15 15 |
10 10 |
11 11 | import foo
12 12 |
13 |-foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
13 |+foo("Hello", U"world", a=u"Hello", b=u"world") # UP025
14 14 |
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
UP025.py:12:15: UP025 [*] Remove unicode literals from strings
UP025.py:13:15: UP025 [*] Remove unicode literals from strings
|
10 | import foo
11 |
12 | foo(u"Hello", U"world", a=u"Hello", b=u"world")
11 | import foo
12 |
13 | foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
| ^^^^^^^^ UP025
13 |
14 | # These should stay quoted they way they are
14 |
15 | # Retain quotes when fixing.
|
= help: Remove unicode prefix
Safe fix
9 9 |
10 10 | import foo
11 11 |
12 |-foo(u"Hello", U"world", a=u"Hello", b=u"world")
12 |+foo(u"Hello", "world", a=u"Hello", b=u"world")
13 13 |
14 14 | # These should stay quoted they way they are
15 15 |
10 10 |
11 11 | import foo
12 12 |
13 |-foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
13 |+foo(u"Hello", "world", a=u"Hello", b=u"world") # UP025
14 14 |
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
UP025.py:12:27: UP025 [*] Remove unicode literals from strings
UP025.py:13:27: UP025 [*] Remove unicode literals from strings
|
10 | import foo
11 |
12 | foo(u"Hello", U"world", a=u"Hello", b=u"world")
11 | import foo
12 |
13 | foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
| ^^^^^^^^ UP025
13 |
14 | # These should stay quoted they way they are
14 |
15 | # Retain quotes when fixing.
|
= help: Remove unicode prefix
Safe fix
9 9 |
10 10 | import foo
11 11 |
12 |-foo(u"Hello", U"world", a=u"Hello", b=u"world")
12 |+foo(u"Hello", U"world", a="Hello", b=u"world")
13 13 |
14 14 | # These should stay quoted they way they are
15 15 |
10 10 |
11 11 | import foo
12 12 |
13 |-foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
13 |+foo(u"Hello", U"world", a="Hello", b=u"world") # UP025
14 14 |
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
UP025.py:12:39: UP025 [*] Remove unicode literals from strings
UP025.py:13:39: UP025 [*] Remove unicode literals from strings
|
10 | import foo
11 |
12 | foo(u"Hello", U"world", a=u"Hello", b=u"world")
11 | import foo
12 |
13 | foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
| ^^^^^^^^ UP025
13 |
14 | # These should stay quoted they way they are
14 |
15 | # Retain quotes when fixing.
|
= help: Remove unicode prefix
Safe fix
9 9 |
10 10 | import foo
11 11 |
12 |-foo(u"Hello", U"world", a=u"Hello", b=u"world")
12 |+foo(u"Hello", U"world", a=u"Hello", b="world")
13 13 |
14 14 | # These should stay quoted they way they are
15 15 |
10 10 |
11 11 | import foo
12 12 |
13 |-foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
13 |+foo(u"Hello", U"world", a=u"Hello", b="world") # UP025
14 14 |
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
UP025.py:16:5: UP025 [*] Remove unicode literals from strings
|
14 | # These should stay quoted they way they are
15 |
16 | x = u'hello'
15 | # Retain quotes when fixing.
16 | x = u'hello' # UP025
| ^^^^^^^^ UP025
17 | x = u"""hello"""
18 | x = u'''hello'''
17 | x = u"""hello""" # UP025
18 | x = u'''hello''' # UP025
|
= help: Remove unicode prefix
Safe fix
13 13 |
14 14 | # These should stay quoted they way they are
15 15 |
16 |-x = u'hello'
16 |+x = 'hello'
17 17 | x = u"""hello"""
18 18 | x = u'''hello'''
19 19 | x = u'Hello "World"'
13 13 | foo(u"Hello", U"world", a=u"Hello", b=u"world") # UP025
14 14 |
15 15 | # Retain quotes when fixing.
16 |-x = u'hello' # UP025
16 |+x = 'hello' # UP025
17 17 | x = u"""hello""" # UP025
18 18 | x = u'''hello''' # UP025
19 19 | x = u'Hello "World"' # UP025
UP025.py:17:5: UP025 [*] Remove unicode literals from strings
|
16 | x = u'hello'
17 | x = u"""hello"""
15 | # Retain quotes when fixing.
16 | x = u'hello' # UP025
17 | x = u"""hello""" # UP025
| ^^^^^^^^^^^^ UP025
18 | x = u'''hello'''
19 | x = u'Hello "World"'
18 | x = u'''hello''' # UP025
19 | x = u'Hello "World"' # UP025
|
= help: Remove unicode prefix
Safe fix
14 14 | # These should stay quoted they way they are
15 15 |
16 16 | x = u'hello'
17 |-x = u"""hello"""
17 |+x = """hello"""
18 18 | x = u'''hello'''
19 19 | x = u'Hello "World"'
14 14 |
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
17 |-x = u"""hello""" # UP025
17 |+x = """hello""" # UP025
18 18 | x = u'''hello''' # UP025
19 19 | x = u'Hello "World"' # UP025
20 20 |
UP025.py:18:5: UP025 [*] Remove unicode literals from strings
|
16 | x = u'hello'
17 | x = u"""hello"""
18 | x = u'''hello'''
16 | x = u'hello' # UP025
17 | x = u"""hello""" # UP025
18 | x = u'''hello''' # UP025
| ^^^^^^^^^^^^ UP025
19 | x = u'Hello "World"'
19 | x = u'Hello "World"' # UP025
|
= help: Remove unicode prefix
Safe fix
15 15 |
16 16 | x = u'hello'
17 17 | x = u"""hello"""
18 |-x = u'''hello'''
18 |+x = '''hello'''
19 19 | x = u'Hello "World"'
15 15 | # Retain quotes when fixing.
16 16 | x = u'hello' # UP025
17 17 | x = u"""hello""" # UP025
18 |-x = u'''hello''' # UP025
18 |+x = '''hello''' # UP025
19 19 | x = u'Hello "World"' # UP025
20 20 |
21 21 | # These should not change
21 21 | u = "Hello" # OK
UP025.py:19:5: UP025 [*] Remove unicode literals from strings
|
17 | x = u"""hello"""
18 | x = u'''hello'''
19 | x = u'Hello "World"'
17 | x = u"""hello""" # UP025
18 | x = u'''hello''' # UP025
19 | x = u'Hello "World"' # UP025
| ^^^^^^^^^^^^^^^^ UP025
20 |
21 | # These should not change
21 | u = "Hello" # OK
|
= help: Remove unicode prefix
Safe fix
16 16 | x = u'hello'
17 17 | x = u"""hello"""
18 18 | x = u'''hello'''
19 |-x = u'Hello "World"'
19 |+x = 'Hello "World"'
16 16 | x = u'hello' # UP025
17 17 | x = u"""hello""" # UP025
18 18 | x = u'''hello''' # UP025
19 |-x = u'Hello "World"' # UP025
19 |+x = 'Hello "World"' # UP025
20 20 |
21 21 | # These should not change
22 22 | u = "Hello"
21 21 | u = "Hello" # OK
22 22 | u = u # OK
UP025.py:29:7: UP025 [*] Remove unicode literals from strings
UP025.py:27:7: UP025 [*] Remove unicode literals from strings
|
27 | return"Hello"
28 |
29 | f"foo"u"bar"
25 | return"Hello" # OK
26 |
27 | f"foo"u"bar" # OK
| ^^^^^^ UP025
30 | f"foo" u"bar"
28 | f"foo" u"bar" # OK
|
= help: Remove unicode prefix
Safe fix
26 26 | def hello():
27 27 | return"Hello"
28 28 |
29 |-f"foo"u"bar"
29 |+f"foo""bar"
30 30 | f"foo" u"bar"
24 24 | def hello():
25 25 | return"Hello" # OK
26 26 |
27 |-f"foo"u"bar" # OK
27 |+f"foo""bar" # OK
28 28 | f"foo" u"bar" # OK
UP025.py:30:8: UP025 [*] Remove unicode literals from strings
UP025.py:28:8: UP025 [*] Remove unicode literals from strings
|
29 | f"foo"u"bar"
30 | f"foo" u"bar"
27 | f"foo"u"bar" # OK
28 | f"foo" u"bar" # OK
| ^^^^^^ UP025
|
= help: Remove unicode prefix
Safe fix
27 27 | return"Hello"
28 28 |
29 29 | f"foo"u"bar"
30 |-f"foo" u"bar"
30 |+f"foo" "bar"
25 25 | return"Hello" # OK
26 26 |
27 27 | f"foo"u"bar" # OK
28 |-f"foo" u"bar" # OK
28 |+f"foo" "bar" # OK

View File

@ -1715,6 +1715,16 @@ bitflags! {
/// ```
const FUTURE_ANNOTATIONS = 1 << 15;
/// The model has traversed past the module docstring.
///
/// For example, the model could be visiting `x` in:
/// ```python
/// """Module docstring."""
///
/// x: int = 1
/// ```
const MODULE_DOCSTRING = 1 << 16;
/// The model is in a type parameter definition.
///
/// For example, the model could be visiting `Record` in:
@ -1723,11 +1733,10 @@ bitflags! {
///
/// Record = TypeVar("Record")
///
const TYPE_PARAM_DEFINITION = 1 << 16;
const TYPE_PARAM_DEFINITION = 1 << 17;
/// The context is in any type annotation.
const ANNOTATION = Self::TYPING_ONLY_ANNOTATION.bits() | Self::RUNTIME_EVALUATED_ANNOTATION.bits() | Self::RUNTIME_REQUIRED_ANNOTATION.bits();
const ANNOTATION = Self::TYPING_ONLY_ANNOTATION.bits() | Self::RUNTIME_EVALUATED_ANNOTATION.bits() | Self::RUNTIME_REQUIRED_ANNOTATION.bits();
/// The context is in any string type definition.
const STRING_TYPE_DEFINITION = Self::SIMPLE_STRING_TYPE_DEFINITION.bits()