1 /**
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lsp/include/register_code_fix/ui_plugin_suggest.h"
17 #include <iostream>
18 #include <string>
19 #include "lsp/include/code_fix_provider.h"
20 #include "lsp/include/internal_api.h"
21
22 namespace ark::es2panda::lsp {
23 const int G_UI_PLUGIN_SUGGEST_CODE = 4000; // change this to the error code you want to handle
24
UIPluginSuggest()25 UIPluginSuggest::UIPluginSuggest()
26 {
27 const char *uiPluginSuggestId = "UIPluginSuggest";
28 SetErrorCodes({G_UI_PLUGIN_SUGGEST_CODE});
29 SetFixIds({uiPluginSuggestId});
30 }
31
GetTextChangesFromSuggestions(const ark::es2panda::util::Diagnostic * diag,size_t pos,bool isAll)32 std::vector<TextChange> GetTextChangesFromSuggestions(const ark::es2panda::util::Diagnostic *diag, size_t pos,
33 bool isAll)
34 {
35 std::vector<TextChange> textChanges;
36 if (!diag->HasSuggestions()) {
37 return textChanges;
38 }
39 for (auto suggestion : diag->Suggestion()) {
40 auto sourceStart = suggestion->SourceRange()->start.index;
41 auto sourceEnd = suggestion->SourceRange()->end.index;
42 auto span = TextSpan(sourceStart, sourceEnd - sourceStart);
43 if (isAll) {
44 textChanges.emplace_back(TextChange(span, suggestion->SubstitutionCode()));
45 } else if (pos >= sourceStart && pos <= sourceEnd) {
46 textChanges.emplace_back(TextChange(span, suggestion->SubstitutionCode()));
47 }
48 }
49 return textChanges;
50 }
51
GetUIPluginCodeFixesByDiagType(public_lib::Context * ctx,size_t pos,util::DiagnosticType type,bool isAll)52 std::vector<FileTextChanges> GetUIPluginCodeFixesByDiagType(public_lib::Context *ctx, size_t pos,
53 util::DiagnosticType type, bool isAll)
54 {
55 auto filename = ctx->sourceFileName;
56 std::vector<FileTextChanges> res;
57 const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(type);
58 auto diagnosticStorage = reinterpret_cast<const ark::es2panda::util::DiagnosticStorage *>(&diagnostics);
59 // NOLINTNEXTLINE(modernize-loop-convert,-warnings-as-errors)
60 for (size_t i = 0; i < diagnosticStorage->size(); ++i) {
61 auto diag = reinterpret_cast<const ark::es2panda::util::Diagnostic *>(&(*(*diagnosticStorage)[i]));
62 auto textChanges = GetTextChangesFromSuggestions(diag, pos, isAll);
63 FileTextChanges fileTextChanges(filename, textChanges);
64 res.emplace_back(fileTextChanges);
65 }
66 return res;
67 }
68
GetUIPluginCodeFixes(es2panda_Context * context,size_t pos,bool isAll)69 std::vector<FileTextChanges> UIPluginSuggest::GetUIPluginCodeFixes(es2panda_Context *context, size_t pos, bool isAll)
70 {
71 if (context == nullptr) {
72 return {};
73 }
74 auto ctx = reinterpret_cast<public_lib::Context *>(context);
75 std::vector<FileTextChanges> res;
76 auto errorFixes = GetUIPluginCodeFixesByDiagType(ctx, pos, util::DiagnosticType::PLUGIN_ERROR, isAll);
77 res.insert(res.end(), errorFixes.begin(), errorFixes.end());
78 auto warningFixes = GetUIPluginCodeFixesByDiagType(ctx, pos, util::DiagnosticType::PLUGIN_WARNING, isAll);
79 res.insert(res.end(), warningFixes.begin(), warningFixes.end());
80 return res;
81 }
82
GetCodeActions(const CodeFixContext & context)83 std::vector<CodeFixAction> UIPluginSuggest::GetCodeActions(const CodeFixContext &context)
84 {
85 std::vector<CodeFixAction> returnedActions;
86 auto changes = GetUIPluginCodeFixes(context.context, context.span.start, false);
87 if (!changes.empty()) {
88 CodeFixAction codeAction;
89 codeAction.fixName = "Fix";
90 codeAction.description = "Fix Description";
91 codeAction.changes = changes;
92 codeAction.fixId = "UI_PLUGIN_SUGGEST";
93 codeAction.fixAllDescription = "Fix All Description";
94 InstallPackageAction codeActionCommand;
95 codeActionCommand.file = reinterpret_cast<public_lib::Context *>(context.context)->sourceFileName;
96 codeActionCommand.packageName = "";
97 codeAction.commands.push_back(codeActionCommand);
98 returnedActions.push_back(codeAction);
99 }
100 return returnedActions;
101 }
102
GetAllCodeActions(const CodeFixAllContext & codeFixAll)103 CombinedCodeActions UIPluginSuggest::GetAllCodeActions(const CodeFixAllContext &codeFixAll)
104 {
105 CombinedCodeActions combinedCodeActions;
106 auto changes = GetUIPluginCodeFixes(codeFixAll.context, 0, true);
107 combinedCodeActions.changes = changes;
108 InstallPackageAction codeActionCommand;
109 codeActionCommand.file = reinterpret_cast<public_lib::Context *>(codeFixAll.context)->sourceFileName;
110 codeActionCommand.packageName = "";
111 combinedCodeActions.commands.push_back(codeActionCommand);
112
113 return combinedCodeActions;
114 }
115 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp)
116 AutoCodeFixRegister<UIPluginSuggest> g_uiPluginSuggest("UIPluginSuggest");
117 } // namespace ark::es2panda::lsp
118