|
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"
|
@@ -3064,6 +3065,37 @@ synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) {
|
3064 | 3065 | return std::make_pair(body, /*typechecked=*/false);
|
3065 | 3066 | }
|
3066 | 3067 |
|
| 3068 | +llvm::SmallString<128> generateMainFunctionText(ASTContext &C, Decl *decl, |
| 3069 | + bool isThrows, bool isAsync) { |
| 3070 | + // Prepare the indent (same as `printRequirementStub`) |
| 3071 | + StringRef ExtraIndent; |
| 3072 | + StringRef CurrentIndent = Lexer::getIndentationForLine( |
| 3073 | + C.SourceMgr, decl->getStartLoc(), &ExtraIndent); |
| 3074 | + |
| 3075 | + llvm::SmallString<128> Text; |
| 3076 | + llvm::raw_svector_ostream OS(Text); |
| 3077 | + ExtraIndentStreamPrinter Printer(OS, CurrentIndent); |
| 3078 | + |
| 3079 | + Printer.printNewline(); |
| 3080 | + Printer.printIndent(); |
| 3081 | + |
| 3082 | + Printer << ExtraIndent << "static func main() "; |
| 3083 | + if (isAsync) |
| 3084 | + Printer << "async "; |
| 3085 | + if (isThrows) |
| 3086 | + Printer << "throws "; |
| 3087 | + |
| 3088 | + /// Print the "{ <#code#> }" placeholder body |
| 3089 | + Printer << "{\n"; |
| 3090 | + Printer.printIndent(); |
| 3091 | + Printer << ExtraIndent << ExtraIndent << getCodePlaceholder(); |
| 3092 | + Printer.printNewline(); |
| 3093 | + Printer.printIndent(); |
| 3094 | + Printer << ExtraIndent << "}\n"; |
| 3095 | + |
| 3096 | + return Text; |
| 3097 | +} |
| 3098 | + |
3067 | 3099 | FuncDecl *
|
3068 | 3100 | SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
|
3069 | 3101 | Decl *D) const {
|
@@ -3189,13 +3221,30 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
|
3189 | 3221 | candidates[0].overloadChoices[locator].choice.getDecl());
|
3190 | 3222 | }
|
3191 | 3223 |
|
| 3224 | + auto location = braces.Start; |
| 3225 | + |
3192 | 3226 | if (!mainFunction) {
|
3193 | 3227 | const bool hasAsyncSupport =
|
3194 | 3228 | AvailabilityRange::forDeploymentTarget(context).isContainedIn(
|
3195 | 3229 | context.getBackDeployedConcurrencyAvailability());
|
3196 |
| - context.Diags.diagnose(attr->getLocation(), |
3197 |
| - diag::attr_MainType_without_main, |
3198 |
| - nominal, hasAsyncSupport); |
| 3230 | + auto params = |
| 3231 | + hasAsyncSupport |
| 3232 | + ? std::vector<std::pair<bool, bool>>{{false, false}, |
| 3233 | + {true, false}, |
| 3234 | + {false, true}, |
| 3235 | + {true, true}} |
| 3236 | + : std::vector<std::pair<bool, bool>>{{false, false}, {true, false}}; |
| 3237 | + |
| 3238 | + auto diag = context.Diags.diagnose(attr->getLocation(), |
| 3239 | + diag::attr_MainType_without_main, |
| 3240 | + nominal, hasAsyncSupport); |
| 3241 | + |
| 3242 | + for (auto [isThrowing, isAsync] : params) { |
| 3243 | + diag.fixItInsertAfter( |
| 3244 | + location, |
| 3245 | + generateMainFunctionText(context, D, isThrowing, isAsync).str()); |
| 3246 | + } |
| 3247 | + |
3199 | 3248 | attr->setInvalid();
|
3200 | 3249 | return nullptr;
|
3201 | 3250 | }
|
|
0 commit comments