Commit Graph

166 Commits

Author SHA1 Message Date
Hamish Knight
39cc1cbb85 [Refactoring] Add some calls to getSemanticsProvidingExpr 2021-05-28 13:10:26 +01:00
Hamish Knight
5ed7cae06f [Refactoring] Rework how conditions are classified
- Expand ConditionType to include `.success` and
`.failure` patterns.
- Introduce ConditionPath to represent whether a
classified condition represents a success or
failure path.
- Add methods to CallbackClassifier that deal with
deciding whether a given condition is a success or
failure path.
- Use these methods to simplify `classifyConditional`.
2021-05-28 13:10:25 +01:00
Hamish Knight
f2d5f38c9b [Refactoring] Remove ConditionType::INVALID
This will make it a little nicer to switch on
ConditionType.
2021-05-28 13:10:25 +01:00
Hamish Knight
10038b6fce [Refactoring] Add async wrapper refactoring action
This allows an async alternative function to be
created that forwards onto the user's completion
handler function through the use of
`withCheckedContinuation`/`withCheckedThrowingContinuation`.

rdar://77802486
2021-05-19 20:46:02 +01:00
Hamish Knight
e4a7a93c73 [Refactoring] Generalize addCallToAsyncMethod
Factor out an `addForwardingCallTo` method that
allows the printing of a call to the old completion
handler function, with a given replacement for the
completion handler arg. `addCallToAsyncMethod` then
calls this with an empty replacement for the handler,
removing it from the call.
2021-05-19 20:46:02 +01:00
Hamish Knight
555f8da8b1 [Refactoring] Add utility method for printing tuples 2021-05-19 20:46:01 +01:00
Hamish Knight
46fa6e5721 [AST] Improve BinaryExpr
Abstract away the TupleExpr gunk and expose
`getLHS` and `getRHS` accessors. This is in
preparation for completely expunging the use
of TupleExpr as an argument list.
2021-05-19 14:48:01 +01:00
Alex Hoppen
b0bade6711 Merge pull request #37417 from bnbarham/add-completionhandler-attribute
[Refactoring] Add @completionHandlerAsync to sync function
2021-05-14 17:09:58 +02:00
Ben Barham
762337cc9b [Refactoring] Add @completionHandlerAsync to sync function
When adding an async alternative, add the @completionHandlerAsync
attribute to the sync function. Check for this attribute in addition to
the name check, ie. convert a call if the callee has either
@completionHandlerAsync or a name that is completion-handler-like name.

The addition of the attribute is currently gated behind the experimental
concurrency flag.

Resolves rdar://77486504
2021-05-14 20:19:02 +10:00
Hamish Knight
7ab5915750 [Refactoring] Don't drop returns with expressions
Previously we were unconditionally dropping a
return statement if it was the last node, which
could cause us to inadvertently drop the result
expression as well. Instead, only drop bare
'return' statements.

rdar://77789360
2021-05-14 11:17:59 +01:00
Hamish Knight
aa189f2fe9 [Refactoring] Avoid duplicating return statements
It's possible the user has already written an
explicit return for the call to the completion
handler. In that case, avoid adding another return.

rdar://77789360
2021-05-14 11:17:59 +01:00
Hamish Knight
d7d58cbbb2 [Refactoring] Tweak handling of return and break placeholders
- Add a missing return to the break statement
placeholder handling.

- Only turn the `return` token into a placeholder,
as we still want to apply the transformation to
the sub expression.

This stops us from crashing by attempting to walk
into the return sub-expression.

rdar://77789360
2021-05-14 11:17:57 +01:00
Hamish Knight
8cb319b640 [Refactoring] Preserve comments in async transform
Previously we would drop comments between nodes in
a BraceStmt, as we printed each node out individually.
To remedy this, always make sure we scan backwards
to find any preceding comments attached to a node,
and also keep track of any SourceLocs which we
don't print, but may have comments attached which
we want to preserve.

rdar://77401810
2021-05-13 14:16:27 +01:00
Hamish Knight
3a7a880fa0 [Refactoring] Store SourceFile on AsyncConverter 2021-05-13 14:16:26 +01:00
Ben Barham
8569c8a51b [Refactoring] Avoid redeclarations or shadowing in async refactored code
When converting a call or function, rename declarations such that
redeclaration errors and shadowing are avoided. In some cases this will
be overly conservative, but since any renamed variable can be fixed with
edit all in scope, this is preferred over causing redeclaration errors
or possible shadowing.

Resolves rdar://73973517
2021-05-13 17:48:41 +10:00
Alex Hoppen
32ceb24b6c [Refactoring] Promote call to refactored completion handlers to return
When a function’s completion handler is being passed to another function and the function that the completion handler is being declared in is converted to async, replace the call to the completion handler by a `return` statement.

For example:
```swift
func foo(completion: (String) -> Void) {
  bar(completion)
}
```

becomes
```swift
func foo() async -> String {
  return await bar()
}
```

Previously, we were calling the completion handler, which no longer exists in the newly created `async` function.
2021-05-12 09:26:25 +02:00
Alex Hoppen
921443e8ab [Refactoring] Support creation of async legacy bodies even if a parameter is not optional
If the parameter is not an `Optional`, add a placeholder instead that the user can fill with a sensible default value.
2021-05-11 15:49:55 +02:00
Alex Hoppen
dd978cca0b [Refactoring] Support refactoring calls to async if a variable or function is used as completion handler
Previously, we only supported  refactoring a function to call the async alternative if a closure was used for the callback parameter. With this change, we also support calling a arbitrary function (or variable with function type) that is passed to the completion handler argument.

The implementation basically re-uses the code we already have to create the legacy function’s body (which calls the newly created async version and then forwards the arguments to the legacy completion handler).

To describe the completion handler that the result is being forwarded to, I’m also using `AsyncHandlerDesc`, but since the completion handler may be a variable, it doesn’t necessarily have an `Index` within a function decl that declares it. Because of this, I split the `AsyncHandlerDesc` up into a context-free `AsyncHandlerDesc` (without an `Index`) and `AsyncHandlerParamDesc` (which includes the `Index`). It turns out that `AsyncHandlerDesc` is sufficient in most places.

Resolves rdar://77460524
2021-05-11 15:48:24 +02:00
Alex Hoppen
b8ec77892c [Refactoring] Replace usage of constant strings with tok:: wherever possible
The code moved from `LegacyAlternativeBodyCreator` was using constant strings a lot. Use `tok::` instead to match the style of `AsyncConverter`.
2021-05-07 18:05:27 +02:00
Alex Hoppen
8903190bed [Refactoring] Merge LegacyAlternativeBodyCreator into AsyncConverter
This will later allow us to reuse parts of `LegacyAlternativeBodyCreator` from `AsyncConverter` when refactoring calls to an async alternative if they pass a variable as the completion handler.
2021-05-07 18:05:27 +02:00
Ben Barham
398124c61a [Refactoring] Only unwrap optionals if the handler has an optional error
Resolves rdar://73973459
2021-05-06 10:27:34 +10:00
Hamish Knight
69caeae420 Merge pull request #37189 from hamishknight/break-it-down-for-me 2021-05-05 10:07:11 +01:00
Alex Hoppen
e835b77956 Merge pull request #37185 from ahoppen/pr/legacy-async-method-refactor
[Refactoring] When adding an async alternative refactor the old method to call the async method using `async`
2021-05-04 18:33:25 +02:00
Hamish Knight
f5acd137e8 [Refactoring] Replace lifted breaks/returns with placeholders
If we're lifting them outside of the control flow
structure they're dealing with, turn them into
placeholders, as they will no longer perform the
control flow the user is expecting.

This handles:
- Return statements at the top-level of the callback.
- Break statements in switches that we re-write.

Resolves rdar://74014897.
2021-05-04 14:30:23 +01:00
Hamish Knight
8a052394aa [Refactoring] Don't transform unrelated switches
We were missing a `return` here to ignore any
switch statements that don't have anything to do
with the error handling.
2021-05-04 14:30:23 +01:00
Hamish Knight
c56f1f867b [Refactoring] Have addCustom take a SourceRange
And have it automatically track to the end of the
token, as that's the behavior we seem to always
want.
2021-05-04 14:30:22 +01:00
Alex Hoppen
98e6680c85 [Refactoring] When adding an async alternative refactor the old method to call the async method using detach
Instead of leaving two copies of the same implementation, rewrite the old method with the completion handler to call the newly added `async` method.

Resolves rdar://74464833
2021-05-04 12:06:27 +02:00
Hamish Knight
fba9d8342f Merge pull request #37174 from hamishknight/off-the-chain
[Refactoring] Unwrap optional chains in async transform
2021-04-30 23:45:38 +01:00
Hamish Knight
07cdc2029e [Refactoring] Unwrap optional chains in async transform
Remove an optional chain of a success parameter,
as it will no longer be optional, similar to how
we remove a force unwrap.

Note that while this is a locally valid transform
within the optional chain, e.g `foo?.x` -> `foo.x`,
it may change the type of the overall chain, which
could cause errors elsewhere in the code. However
this is generally more useful to the user than
just leaving `foo` as a placeholder. Note this is
only the case when no other optionals are involved
in the chain, e.g `foo?.x?.y` -> `foo.x?.y` is
completely valid.

Resolves rdar://74014826.
2021-04-30 14:34:31 +01:00
Alex Hoppen
b2378a401e [Refactoring] Convert completion handler when converting function to async
Convert function to async currently only adds "async" to the function and runs the convert call refactoring on the body.

This was intentional, but it turns out to be somewhat confusing. Instead, run the same refactoring as the add async alternative refactoring but just replace rather than add.

Resolves rdar://77103049
2021-04-30 12:53:22 +02:00
Hamish Knight
c1e4dc3d82 [Refactoring] Improve Void handling for async conversion
When converting a function with a completion handler
that has a Void success parameter, e.g
`(Void?, Error?) -> Void`, or more likely a
`Result<Void, Error>` parameter, make sure to omit
the `-> Void` from the resulting async function
conversion.

In addition, strip any Void bindings from an async
function call, and any explicit Void return values
from inside the async function.

Resolves rdar://75189289
2021-04-30 01:09:04 +01:00
Alex Hoppen
1bd6086cbf Merge pull request #37071 from ahoppen/pr/block-convention-to-async
[Refactoring] Support refactoring to async if callback is `@convention(block)`
2021-04-28 11:40:19 +02:00
Alex Hoppen
f17fe868c6 [Refactoring] Support refactoring to async if callback is @convention(block)
We already have special logic to extrac the closure for closures with capture lists, add the same kind of logic for closures that are marked `@convention(block)` etc.

Resolves rdar://75301524 [SR-14328]
2021-04-27 22:25:57 +02:00
Alex Hoppen
16adf76b68 Merge pull request #36994 from ahoppen/pr/refactor-protocol-requirement-async
[Refactoring] Fix crash when refactoring protocol requirement to async
2021-04-22 17:02:44 +02:00
Alex Hoppen
9d62f9d4db [Refactoring] Fix crash when refactoring protocol requirement to async
When a function declaration has no body (e.g. because it’s a protocol requirement), we construct the range to replace by the `async` keyword as follows:
- Start: One character after the closing `)` (or potentially the `throws` keyword if it exists)
- End: Last token in the function declaration

Since the last token in the function declaration is the `)`, we end up with a range that has `End < Start`, which crashes when trying to print the range.

If the function has no body, we should just use the range’s start location as the end location to construct an empty range.

Fixes rdar://76677035
2021-04-22 11:56:34 +02:00
Azoy
9ed732f0ab Introduce isDecl and getDeclType
fix enum logic issue

fix tests

guard against null types
2021-04-20 02:22:16 -04:00
Ben Barham
20f45ec284 Replace uses of presumed locations where they do not make sense
Various uses of `getPresumedLineAndColumnForLoc` were likely added when
that function was the very misleading name `getLineAndColumn`. Change
these to use `getLineAndColumnForBuffer` instead where appropriate, ie.
we want the underlying file rather than the location to display to the
user.

There were also some cases where the buffer identifier had been swapped
to use the display name instead, under the assumption that the presumed
location was needed. Updated those as well.

SingleRawComment: Lines are only used when merging comments, where the
original location is fine to use.

Index: Doesn't store the file set in #sourceLocation, so using the
presumed line would end up pointing to a location that makes no sense.

Editor functionality: Formatting and refactoring are on the current
file. Using the presumed location would result in incorrect
replacements.
2021-04-10 09:49:31 +10:00
Ben Barham
3ea9bed415 [SourceKit/CursorInfo] Add constructor to call results
Cursor info for a constructor would previously give the cursor info for
the containing type only. It now also adds cursor info for the
constructor itself in a "secondary_symbols" field.

Refactor `passCursorInfoForDecl` to use a single allocator rather than
keeping track of positions in a buffer and assigning everything at the
end of the function.

Refactor the various available refactoring gathering functions to take a
SmallVectorImpl and to not copy strings where they don't need to.

Resolves rdar://75385556
2021-03-30 13:23:59 +10:00
Ben Barham
0717448611 [Refactoring] Handle default arguments when converting call to async
Default arguments were still being visited when converting the call,
adding extra commas to the converted call. Skip over them.

Resolves rdar://74248990
2021-02-12 08:18:55 +10:00
Ben Barham
384b309f89 [Refactoring] Only convert calls with handlers that have completion-like names
Still convert the call if it was requested directly - only check the name
when converting a whole function. Once we have an attribute, we should
use that instead.
2021-02-12 07:43:57 +10:00
Ben Barham
bc5229701e [Refactoring] Handle closures with capture list in async refactoring
Resolves rdar://74064061
2021-02-12 07:43:57 +10:00
Ben Barham
9cddf498de [Refactoring] Replace attributes when converting to an async function
The replacement range was `FunctionDecl::getRange`, which does not
include attributes. This would cause attributes to be duplicated when
converting a function to async. Override the start with the attribute
start instead so that they are replaced as well.

Resolves rdar://74063741
2021-02-12 07:43:57 +10:00
Ben Barham
33bc38cdb8 [IDE] SourceEntityWalker should walk all explicit declarations
`SourceEntityWalker` had an unbalanced `walkToDeclPre` and
`walkToDeclPost`, ie. `walkToDeclPost` could be called even though
`walkToDeclPre` was not. Specifically, this would occur for both
`OperatorDecl` and `PrecedenceGroupDecl` declarations.

These could both be added to the `if` in `walkToDeclPost`, but this
seems fairly errorprone in general - especially as new decls are added.
Indeed, there's already declarations that are being skipped because they
aren't explicitly tested for in `walkToDeclPre`, ie.
`PatternBindingDecl`.

Instead of skipping if not explcitly handled, only skip running the
`SEWalker` walk methods if the declaration is implicit (and not a
constructor decl, see TODO). This should probably also always visit
children, with various decls changed to become implicit (eg.
TopLevelCodeDecl), but we can do that later - breaks too many tests for
now.

This change exposed a few parameter declarations that were missing their
implicit flag, as well as unbalanced walk methods in `RangeResolver`.
2021-02-11 10:34:07 +10:00
Doug Gregor
5013d20b86 Merge pull request #35784 from DougGregor/se-0296 2021-02-05 20:10:48 -08:00
Doug Gregor
238290cdc4 [SE-0296] Enable async/await by default.
Always parse `async` and `await`, allowing the definition and use of
asynchronous functions without the "experimental concurrency" flag.

Note that, at present, use of asynchronous functions requires one to
explicitly import or link against the `_Concurrency` library. We'll
sort this out in a follow-up change.

Tracked by rdar://73455330.
2021-02-05 09:51:46 -08:00
Varun Gandhi
0d1e7abc9a Merge pull request #35757 from cypherean/refactor_transform
Replace std::transform with llvm::transform
2021-02-05 08:17:48 -08:00
Ben Barham
783c177956 [Refactoring] Fix stack use after free in new async refactorings
Resolves rdar://73984220
2021-02-05 15:32:35 +10:00
shreyaa-sharmaa
2b11d7acc7 Task SR-14138 Replace std::transform with llvm::transform 2021-02-04 12:58:33 +05:30
Ben Barham
a9073b0922 [Refactoring] Add async refactorings
Adds three refactorings intended to help users migrate their existing
code to use the new async language features:
  1. Convert call to use async alternative
  2. Convert function to async
  3. Add async alternative function

A function is considered to have an async alternative if it has a void
return type and has a void returning closure as its last parameter. A
method to explicitly mark functions as having an async alternative may
be added to make this more accurate in the future (required for eg.
a warning about a call to the non-async version of a function in an
async context).

(1) converts a call to use the new `await` async language syntax. If the
async alternative throws, it will also add `try`. The closure itself is
hoisted out of the call, see the comments on
`AsyncConversionStringBuilder` for specifics.

(2) converts a whole function to `async`, using (1) to convert any calls
in the function to their async alternatives. (3) is similar to (2), but
instead *adds* a function and replaces calls to its
completion/handler/callback closure parameter with `return` or `throws`.

Resolves rdar://68254700
2021-02-03 15:54:46 +10:00
Ben Barham
0f09d4107a [Gardening] Pass resolved cursor/range info by reference 2021-02-03 15:54:45 +10:00