Commit Graph

80 Commits

Author SHA1 Message Date
7b59a2e3ea mparser: Use a literal for the ComparisonNode
And fix a bug where `not in` is in the wrong order.
2023-01-17 15:14:53 -08:00
8f9c6c10c4 mparser: Don't create an exception to pass to mlog.warning
Just call `mlog.code_line` directly, since the exception is never raised.
2023-01-03 14:49:02 -05:00
7460ab20cd mlog: move code for printing code with a caret to the mlog module
We need this outside the constructor for the ParseException class, so
let's pull it out. mlog seemed like a good place since it's a text
formatting function, and has no dependencies.
2023-01-03 14:49:02 -05:00
3e55891ae7 mparser: don't pass a SimpleNamespace where a BaseNode is expected
mypy spotted this as well. And it turns out that we're not setting the
column either for the warning, so improvements!
2023-01-03 14:49:02 -05:00
e5a9272034 typing: fix some broken Sequence annotations
T.Sequence is a questionable concept. The idea is to hammer out generic,
maximally forgiving APIs that operate on protocols, which is a fancy way
of saying "I don't care if you use tuples or lists". This is rarely
needed, actually, and in exchange for this fancy behavior you get free
bugs.

Specifically, `somestr` is of type `T.Sequence[str]`, and also
`somestr[0]` is another string of type you guessed it. It's ~~turtles~~
strings all the way down.

It's worth noting that trying to code for "protocols" is a broken
concept if the contents have semantic meaning, e.g. it operates on
"the install tags of this object" rather than "an iterable that supports
efficient element access".

The other way to use T.Sequence is "I don't like that T.List is
invariant, but also I don't like that T.Tuple makes you specify exact
ordering". This sort of works. In fact it probably does work as long as
you don't allow str in your sequences, which of course everyone allows
anyway.

Use of Sequence has cute side effects, such as actually passing lists
around, knowing that you are going to get a list and knowing that you
need to pass it on as a list, and then having to re-allocate as
`list(mylist)` "because the type annotations says it could be a str or
tuple".

Except it cannot be a str, because if it is then the application is
fatally flawed and logic errors occur to disastrous end user effects,
and the type annotations:
- do not enforce their promises of annotating types
- fail to live up to "minimal runtime penalties" due to all the `list()`

Shun this broken concept, by hardening the type annotations. As it turns
out, we do not actually need any of this covariance or protocol-ism for
a list of strings! The whole attempt was a slow, buggy waste of time.
2022-12-11 18:28:39 -05:00
4da14918cd pylint: enable consider-using-in 2022-09-19 20:57:52 -04:00
d771fc7d0b Add support for multiline f-strings
+ Extend the parser to recognize the multiline f-strings, which the
documentation already implies will work.

The syntax is like:
```
x = 'hello'
y = 'world'

msg = f'''This is a multiline string.

Sending a message: '@x@ @y@'
'''
```

which produces:
```
This is a multiline string.

Sending a message: 'hello world'

```

+ Added some f-string tests cases to "62 string arithmetic" to exercise
the new behavior.
2022-05-01 12:47:37 -04:00
2974f2bcb8 fix malformed warning to print the way it was meant to print
Given a meson.build with the contents:

```
t = '
'
```

We want to warn that this is bad. So we emitted this warning:
```
WARNING: Newline character in a string detected, use ''' (three single quotes) for multiline strings instead.
This will become a hard error in a future Meson release.                                 t = ' 4 4
```

The line contents and the offset are printed as gibberish after a big
whitespace run. These are elsewhere often passed to ParseException,
which pretty-prints this, but newlines aren't an exception, merely a
warning, and mlog.warning doesn't accept numeric strings as anything
more meaningful than something to print as text.

Fix this (by wrapping it in a ParseException) to properly print:
```
meson.build:4: WARNING: Newline character in a string detected, use ''' (three single quotes) for multiline strings instead.
This will become a hard error in a future Meson release.
t = '
    ^
```
2022-02-16 23:00:28 -05:00
aa0450adda fix a couple misuses of textwrap.dedent
A backslash-escape of the last newline before a run of whitespace
leading to the indented string ending and function termination `)` does
not actually escape the entire line and make it do nothing. In fact what
it does is cause all that whitespace to be part of the preceding line,
and get printed.

Meanwhile the textwrap.dedent documentation states that lines with only
whitespace get normalized. When you *don't* mess with that final line,
dedent actually does the right thing and makes the output message end
with a single newline after the important text.
2022-02-16 22:59:48 -05:00
4b351aef26 first pass at migrating to dataclasses
In some cases, init variables that accept None as a sentinel and
immediately overwrite with [], are migrated to dataclass field
factories. \o/

Note: dataclasses by default cannot provide eq methods, as they then
become unhashable. In the future we may wish to opt into declaring them
frozen, instead/additionally.
2022-01-10 18:36:57 -05:00
4d7031437c pylint: turn on superflous-parens
We have a lot of these. Some of them are harmless, if unidiomatic, such
as `if (condition)`, others are potentially dangerous `assert(...)`, as
`assert(condtion)` works as expected, but `assert(condition, message)`
will result in an assertion that never triggers, as what you're actually
asserting is `bool(tuple[2])`, which will always be true.
2021-08-31 16:28:54 -04:00
278942a447 pylint: enable consider-iterating-dictionary
This didn't actually catch what it's supposed to, which is cases of:
```python
for x in dict.keys():
    y = dict[x]
```
But it did catch one unnecessary use of keys(), and one case where we
were doing something in an inefficient way. I've rewritten:
```python
if name.value in [x.value for x in self.kwargs.keys() if isinstance(x, IdNode)]:
```
as
``python
if any((isinstance(x, IdNode) and name.value == x.value) for x in self.kwargs):
```
Which avoids doing two iterations, one to build the list, and a
second to do a search for name.value in said list, which does a single
short circuiting walk, as any returns as soon as one check returns True.
2021-08-31 16:28:54 -04:00
130adef778 Add support for basic format strings 2021-03-10 08:55:22 -05:00
6a0fabc647 mass rewrite of string formatting to use f-strings everywhere
performed by running "pyupgrade --py36-plus" and committing the results
2021-03-04 17:16:11 -05:00
e681235e5f typing: fix code review 2020-09-08 20:15:58 +02:00
fb9738b8c7 typing: fully annotate mparser.py 2020-09-08 20:15:56 +02:00
96eeef62ea ast: Add AST JSON printer 2020-05-23 18:13:16 +02:00
2cfbb36a84 mparser: fix precedence of arithmetic operators
The arithmetic operators are now split into two groups:
    * The add/sub group: +, -
    * The mul/div group: *, /, %

All operators within the same group are left-associative and have equal
precedence. The mul/div group has a higher precedence than the add/sub
group, as one would expect.

Previously every operator had a different precedence and was
right-associative, which resulted in surprising behavior.

This is a potentially breaking change for projects that relied on the
old incorrect behavior.

Fixes #6870
2020-04-04 13:31:07 +03:00
d67888bf9b types: Remove redundant __init__() -> None annotation 2020-03-02 10:52:59 +01:00
0302a697b8 types: Use import typing as T 2020-03-02 10:51:07 +01:00
ab988198c7 review: Initial fixup 2020-03-02 10:47:20 +01:00
a75255bc4c types: Annotate the AST visitors 2020-03-02 10:34:55 +01:00
c14aea2812 types: Annotate mparser.py
This also fixes that the keys in ArgumentNode.kwargs are
all of the type BaseNode now. Before this commit, it was
possible that both strings and Nodes where used as keys.
2020-03-02 10:34:55 +01:00
c8f8d58273 Rename 'subdir' -> 'filename' in location objects 2020-02-28 11:54:08 +00:00
e4a0ee205d lgtm: Fix redundant code 2019-12-05 00:22:10 +02:00
9b1a857473 dict: Fully evaluate keys
The only restriction is keys must be string after evaluation. This fix
various inconsistencies.
2019-12-04 16:45:56 -05:00
80bfe593fc mparser.py: actually check the type of key variable, not its value
Fixes PR #6166 and more specifically commit 4e460f04f3 that tried to
make sure the type of a key variable is a string but checked the type of
the value instead. Extends test common/228's limited coverage,
its only test case had (surprise) a string value. Also avoid reserved
python keyword 'dict' and potentially confusing string 'key'.

Implements #5231 for real.
2019-12-03 22:10:07 -05:00
4e460f04f3 Fixed issue that the key's value type wasn't checked correctly.
Added two new failing tests.
2019-11-12 09:21:10 -05:00
adb4e071e6 Adding dictionary entry using string variable as key. 2019-11-12 09:21:10 -05:00
2b5831f94f Fix flake8-bugbear warnings 2019-04-29 12:22:50 +02:00
ccc4ce28cc consistent invalid escape sequence behaviour
* docs: document unrecognized escape sequence behaviour [skip ci]

Document that unrecognized escape sequence behaviour is like python, not
C.

* Don't try to decode invalid hex escape sequences

Don't try to decode escape sequences which should contain a sequence of
hex digits, but don't, throwing a python exception.  These will treated
literally instead.

* Extend test case to cover invalid escape sequences
2019-04-28 23:06:36 +03:00
5a22bb7901 rewriter: Use mparser to detect the end of some nodes 2019-03-03 13:57:25 +02:00
841da29d2c Fix ternary in thing (#5007)
* tests: extend ternary test to cover bugs

See issues #5003, #3690, and #2404

* mparser: store subdir in ternary node

Ternaries don't really need subdirs, but they can be passed into
functions that expect the type they're provided to have a
subdir. Provide it to fulful the interface.

Fixes #5003
Fixes #3690
Fixes #2404
2019-03-02 12:57:24 +02:00
4b7b5a7185 Fixed flake8 2019-02-16 14:17:02 +01:00
24a2cf02e2 Can now find the assignment node of a value 2019-02-16 14:10:08 +01:00
da34bea893 pep8 py37 2019-01-29 22:06:11 +02:00
e089eb7665 Fixed line and column numbers for dict and array nodes 2019-01-22 16:41:25 +01:00
ccad493e85 Basic AST visitor pattern 2019-01-22 16:09:34 +01:00
90c9b868b2 parser: Fix line continuation outside of (), [] or {}
The documentation states: "In other cases you can get multi-line
statements by ending the line with a \." but that seems to never have
worked.

Closes: #4720
2019-01-05 21:45:37 +02:00
a816e1c1fa Interpreter: Add 'continue' and 'break' keywords
Closes: #3601
2018-10-04 20:14:37 -04:00
fa2e096aa0 Interpreter: Add "in" and "not in" operators
Closes: #3600
2018-10-04 20:14:37 -04:00
e7dcf5cf16 Warn for future keyword (#3908) 2018-07-27 14:31:54 +03:00
86d2f57e86 Add support for octal and binary int literals.
Simplify support for alternate bases using int(..., base=0) which
auto-detects it using the standard Python syntax for numbers.

Octal numbers are useful to specify permission bits and umasks.

Binary numbers are not super useful... But considering we get them for
free, let's allow them here too.

v2: Tweak the regex so it doesn't accept a decimal number with a leading
zero, which is invalid for int(..., base=0) and would raise a ValueError
if passed around.
2018-05-23 14:07:38 -07:00
10e7566ed8 dict: fix CI issues 2018-05-21 00:19:31 +02:00
195c356f91 dict: address review comments 2018-05-20 22:36:18 +02:00
ecb8838082 Add new built-in type, dict
For now dicts are immutable, and do not expose any methods,
they however support "native" syntax such as [] lookup,
and foreach iterating, and can be printed.
2018-05-20 21:19:44 +02:00
cb0960a91e Remove escaping for triple-quoted strings
Fixes #3429
2018-04-21 22:57:19 +03:00
348248f0a1 Exit meson with an error if an invalid escape sequence is found in a
string
2018-04-17 09:55:34 +00:00
36aab0f4b2 Complete python escape sequences aware strings
Fixes #3169
2018-04-17 09:55:34 +00:00
d0f2f0ad3b Newlines in single line strings should only be a warning for now. 2018-02-21 19:09:35 +02:00