|
22 | 22 | #include "TypeCheckObjC.h"
|
23 | 23 | #include "TypeCheckType.h"
|
24 | 24 | #include "TypeChecker.h"
|
| 25 | +#include "swift/AST/ASTPrinter.h" |
25 | 26 | #include "swift/AST/ASTVisitor.h"
|
26 | 27 | #include "swift/AST/AvailabilityInference.h"
|
27 | 28 | #include "swift/AST/ClangModuleLoader.h"
|
@@ -3081,6 +3082,36 @@ synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) {
|
3081 | 3082 | return std::make_pair(body, /*typechecked=*/false);
|
3082 | 3083 | }
|
3083 | 3084 |
|
| 3085 | +static llvm::SmallString<128> |
| 3086 | +generateMainFunctionText(ASTContext &C, NominalTypeDecl *parentDecl, |
| 3087 | + bool isThrows, bool isAsync) { |
| 3088 | + StringRef ExtraIndent; |
| 3089 | + StringRef CurrentIndent = Lexer::getIndentationForLine( |
| 3090 | + C.SourceMgr, parentDecl->getStartLoc(), &ExtraIndent); |
| 3091 | + std::string MethodIndent = (CurrentIndent + ExtraIndent).str(); |
| 3092 | + |
| 3093 | + llvm::SmallString<128> Text; |
| 3094 | + llvm::raw_svector_ostream OS(Text); |
| 3095 | + ExtraIndentStreamPrinter Printer(OS, MethodIndent); |
| 3096 | + |
| 3097 | + Printer.printNewline(); |
| 3098 | + |
| 3099 | + Printer << "static func main() "; |
| 3100 | + if (isAsync) |
| 3101 | + Printer << "async "; |
| 3102 | + if (isThrows) |
| 3103 | + Printer << "throws "; |
| 3104 | + |
| 3105 | + // Print the "{ <#code#> }" placeholder body. |
| 3106 | + Printer << "{\n"; |
| 3107 | + Printer.printIndent(); |
| 3108 | + Printer << ExtraIndent << getCodePlaceholder(); |
| 3109 | + Printer.printNewline(); |
| 3110 | + Printer << "}\n"; |
| 3111 | + |
| 3112 | + return Text; |
| 3113 | +} |
| 3114 | + |
3084 | 3115 | FuncDecl *
|
3085 | 3116 | SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
|
3086 | 3117 | Decl *D) const {
|
@@ -3210,9 +3241,43 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
|
3210 | 3241 | const bool hasAsyncSupport =
|
3211 | 3242 | AvailabilityRange::forDeploymentTarget(context).isContainedIn(
|
3212 | 3243 | context.getBackDeployedConcurrencyAvailability());
|
3213 |
| - context.Diags.diagnose(attr->getLocation(), |
3214 |
| - diag::attr_MainType_without_main, |
3215 |
| - nominal, hasAsyncSupport); |
| 3244 | + |
| 3245 | + auto location = attr->getLocation(); |
| 3246 | + auto fixLocation = braces.Start; |
| 3247 | + |
| 3248 | + context.Diags.diagnose(location, diag::attr_MainType_without_main, nominal, |
| 3249 | + hasAsyncSupport); |
| 3250 | + |
| 3251 | + // Offer fix-its to add the `main` function for different combinations of |
| 3252 | + // effects, starting with no effects. |
| 3253 | + |
| 3254 | + context.Diags.diagnose(location, diag::note_add_main_sync) |
| 3255 | + .fixItInsertAfter(fixLocation, generateMainFunctionText( |
| 3256 | + context, nominal, /*isThrows*/ false, |
| 3257 | + /*isAsync*/ false) |
| 3258 | + .str()); |
| 3259 | + |
| 3260 | + context.Diags.diagnose(location, diag::note_add_main_sync_throws) |
| 3261 | + .fixItInsertAfter(fixLocation, generateMainFunctionText( |
| 3262 | + context, nominal, /*isThrows*/ true, |
| 3263 | + /*isAsync*/ false) |
| 3264 | + .str()); |
| 3265 | + |
| 3266 | + if (hasAsyncSupport) { |
| 3267 | + context.Diags.diagnose(location, diag::note_add_main_async) |
| 3268 | + .fixItInsertAfter(fixLocation, |
| 3269 | + generateMainFunctionText(context, nominal, |
| 3270 | + /*isThrows*/ false, |
| 3271 | + /*isAsync*/ true) |
| 3272 | + .str()); |
| 3273 | + |
| 3274 | + context.Diags.diagnose(location, diag::note_add_main_async_throws) |
| 3275 | + .fixItInsertAfter(fixLocation, |
| 3276 | + generateMainFunctionText(context, nominal, |
| 3277 | + /*isThrows*/ true, |
| 3278 | + /*isAsync*/ true) |
| 3279 | + .str()); |
| 3280 | + } |
3216 | 3281 | attr->setInvalid();
|
3217 | 3282 | return nullptr;
|
3218 | 3283 | }
|
|
0 commit comments