Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Add support for adding constructor #244

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/codeaction/implementconstructoraction.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* implementconstructoraction.vala
*
* Copyright 2022 JCWasmx86 <[email protected]>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

using Lsp;
using Gee;

class Vls.ImplementConstructorAction : CodeAction {
public ImplementConstructorAction (Vala.ObjectCreationExpression oce, Vala.Symbol to_be_created) {
var target_file = to_be_created.source_reference.file;
var insertion_line = to_be_created.source_reference.end.line + 1;
var sb = new StringBuilder ();
var indent = to_be_created.source_reference.begin.column == 1 ? "" : "\t";
sb.append (indent).append (indent).append ("public ").append (oce.member_name.to_string ()).append (" (");
var args = oce.get_argument_list ();
var idx = 0;
for (var i = 0; i < args.size - 1; i++) {
sb.append (args[i].value_type.to_string ()).append (" arg%d".printf (idx++)).append (", ");
}
if (args.size != 0)
sb.append (args[args.size - 1].value_type.to_string ()).append (" arg%d".printf (idx));
sb.append (") {}\n ");
try {
var target_uri = Filename.to_uri (target_file.filename);
var target_document = new VersionedTextDocumentIdentifier () {
uri = target_uri,
version = 1
};
var workspace_edit = new WorkspaceEdit ();
var document_edit = new TextDocumentEdit (target_document);
var r = new Range.from_sourceref (
new Vala.SourceReference (target_file,
Vala.SourceLocation (null, insertion_line, 1),
Vala.SourceLocation (null, insertion_line, 1)));
var text_edit = new TextEdit (r);
document_edit.edits.add (text_edit);
workspace_edit.documentChanges = new Gee.ArrayList<TextDocumentEdit> ();
workspace_edit.documentChanges.add (document_edit);
this.edit = workspace_edit;
this.title = "Add constructor";
text_edit.newText = sb.str;
} catch (ConvertError ce) {
error ("Should not happen: %s", ce.message);
}
}
}
42 changes: 33 additions & 9 deletions src/codehelp/codeaction.vala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ using Vala;

namespace Vls.CodeActions {
/**
* Extracts a list of code actions for the given document and range.
* Extracts a list of code actions for the given document and range using the AST and the diagnostics.
*
* @param file the current document
* @param range the range to show code actions for
* @param uri the document URI
*/
Collection<CodeAction> extract (Compilation compilation, TextDocument file, Range range, string uri) {
Collection<CodeAction> generate_codeactions (Compilation compilation, TextDocument file, Range range, string uri, Reporter reporter) {
// search for nodes containing the query range
var finder = new NodeSearch (file, range.start, true, range.end);
var code_actions = new ArrayList<CodeAction> ();
Expand All @@ -41,13 +41,14 @@ namespace Vls.CodeActions {

// add code actions
foreach (CodeNode code_node in finder.result) {
critical ("%s", code_node.type_name);
if (code_node is IntegerLiteral) {
var lit = (IntegerLiteral)code_node;
var lit = (IntegerLiteral) code_node;
var lit_range = new Range.from_sourceref (lit.source_reference);
if (lit_range.contains (range.start) && lit_range.contains (range.end))
code_actions.add (new BaseConverterAction (lit, document));
} else if (code_node is Class) {
var csym = (Class)code_node;
var csym = (Class) code_node;
var clsdef_range = compute_class_def_range (csym, class_ranges);
var cls_range = new Range.from_sourceref (csym.source_reference);
if (cls_range.contains (range.start) && cls_range.contains (range.end)) {
Expand All @@ -57,6 +58,29 @@ namespace Vls.CodeActions {
code_actions.add (new ImplementMissingPrereqsAction (csym, missing.first, missing.second, clsdef_range.end, code_style, document));
}
}
} else if (code_node is ObjectCreationExpression) {
var oce = (ObjectCreationExpression) code_node;
foreach (var diag in reporter.messages) {
if (file.filename != diag.loc.file.filename)
continue;
if (!(oce.source_reference.contains (diag.loc.begin) || oce.source_reference.contains (diag.loc.end)))
continue;
if (diag.message.contains (" extra arguments for ")) {
var to_be_created = oce.type_reference.symbol;
if (!(to_be_created is Vala.Class)) {
continue;
}
var constr = ((Vala.Class) to_be_created).constructor;
if (constr != null) {
continue;
}
var target_file = to_be_created.source_reference.file;
// We can't just edit, e.g. some external vapi
if (!compilation.get_project_files ().contains (target_file))
continue;
code_actions.add (new ImplementConstructorAction (oce, to_be_created));
}
}
}
}

Expand All @@ -72,11 +96,11 @@ namespace Vls.CodeActions {
// otherwise compute the result and cache it
// csym.source_reference must be non-null otherwise NodeSearch wouldn't have found csym
var pos = new Position.from_libvala (csym.source_reference.end);
var offset = csym.source_reference.end.pos - (char *)csym.source_reference.file.content;
var offset = csym.source_reference.end.pos - (char*) csym.source_reference.file.content;
var dl = 0;
var dc = 0;
while (offset < csym.source_reference.file.content.length && csym.source_reference.file.content[(long)offset] != '{') {
if (Util.is_newline (csym.source_reference.file.content[(long)offset])) {
while (offset < csym.source_reference.file.content.length && csym.source_reference.file.content[(long) offset] != '{') {
if (Util.is_newline (csym.source_reference.file.content[(long) offset])) {
dl++;
dc = 0;
} else {
Expand All @@ -93,8 +117,8 @@ namespace Vls.CodeActions {
if (member.source_reference == null)
continue;
range = range.union (new Range.from_sourceref (member.source_reference));
if (member is Method && ((Method)member).body != null && ((Method)member).body.source_reference != null)
range = range.union (new Range.from_sourceref (((Method)member).body.source_reference));
if (member is Method && ((Method) member).body != null && ((Method) member).body.source_reference != null)
range = range.union (new Range.from_sourceref (((Method) member).body.source_reference));
}
class_ranges[csym] = range;
return range;
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ vls_src = files([
'analysis/codestyleanalyzer.vala',
'analysis/symbolenumerator.vala',
'codeaction/baseconverteraction.vala',
'codeaction/implementconstructoraction.vala',
'codeaction/implementmissingprereqsaction.vala',
'codehelp/callhierarchy.vala',
'codehelp/codeaction.vala',
Expand Down
2 changes: 1 addition & 1 deletion src/server.vala
Original file line number Diff line number Diff line change
Expand Up @@ -1645,7 +1645,7 @@ class Vls.Server : Jsonrpc.Server {
var json_array = new Json.Array ();

Vala.CodeContext.push (compilation.code_context);
var code_actions = CodeActions.extract (compilation, (TextDocument) source_file, p.range, Uri.unescape_string (p.textDocument.uri));
var code_actions = CodeActions.generate_codeactions (compilation, (TextDocument) source_file, p.range, Uri.unescape_string (p.textDocument.uri), compilation.reporter);
foreach (var action in code_actions)
json_array.add_element (Json.gobject_serialize (action));
Vala.CodeContext.pop ();
Expand Down