Allow tabs for the indentation added by code actions. (#684)
* Allow tabs for the indentation added by the code actions feature (#673). The previous implementation always assumed spaces for indentation. But in stage2 code may contain tabs for indentation as well. * Fix some edge cases, properly detect indentation(any amount of spaces) and move the indentation code inside `createDiscardText()`.
This commit is contained in:
parent
19fd17ff76
commit
62861193a6
@ -18,7 +18,7 @@ pub const Builder = struct {
|
|||||||
pub fn generateCodeAction(
|
pub fn generateCodeAction(
|
||||||
builder: *Builder,
|
builder: *Builder,
|
||||||
diagnostic: types.Diagnostic,
|
diagnostic: types.Diagnostic,
|
||||||
actions: *std.ArrayListUnmanaged(types.CodeAction),
|
actions: *std.ArrayListUnmanaged(types.CodeAction)
|
||||||
) error{OutOfMemory}!void {
|
) error{OutOfMemory}!void {
|
||||||
const kind = DiagnosticKind.parse(diagnostic.message) orelse return;
|
const kind = DiagnosticKind.parse(diagnostic.message) orelse return;
|
||||||
|
|
||||||
@ -113,8 +113,7 @@ fn handleUnusedFunctionParameter(builder: *Builder, actions: *std.ArrayListUnman
|
|||||||
|
|
||||||
const block = node_datas[payload.func].rhs;
|
const block = node_datas[payload.func].rhs;
|
||||||
|
|
||||||
const indent = offsets.lineSliceUntilIndex(builder.handle.text, token_starts[node_tokens[payload.func]]).len;
|
const new_text = try createDiscardText(builder, identifier_name, token_starts[node_tokens[payload.func]], true);
|
||||||
const new_text = try createDiscardText(builder.arena.allocator(), identifier_name, indent + 4);
|
|
||||||
|
|
||||||
const index = token_starts[node_tokens[block]] + 1;
|
const index = token_starts[node_tokens[block]] + 1;
|
||||||
|
|
||||||
@ -159,11 +158,9 @@ fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnma
|
|||||||
const first_token = tree.firstToken(node);
|
const first_token = tree.firstToken(node);
|
||||||
const last_token = ast.lastToken(tree, node) + 1;
|
const last_token = ast.lastToken(tree, node) + 1;
|
||||||
|
|
||||||
const indent = offsets.lineSliceUntilIndex(builder.handle.text, token_starts[first_token]).len;
|
|
||||||
|
|
||||||
if (token_tags[last_token] != .semicolon) return;
|
if (token_tags[last_token] != .semicolon) return;
|
||||||
|
|
||||||
const new_text = try createDiscardText(builder.arena.allocator(), identifier_name, indent);
|
const new_text = try createDiscardText(builder, identifier_name, token_starts[first_token], false);
|
||||||
|
|
||||||
const index = token_starts[last_token] + 1;
|
const index = token_starts[last_token] + 1;
|
||||||
|
|
||||||
@ -243,6 +240,30 @@ fn handlePointlessDiscard(builder: *Builder, actions: *std.ArrayListUnmanaged(ty
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn detectIndentation(source: []const u8) []const u8 {
|
||||||
|
// Essentially I'm looking for the first indentation in the file.
|
||||||
|
var i: usize = 0;
|
||||||
|
var len = source.len - 1; // I need 1 look-ahead
|
||||||
|
while(i < len) : (i += 1) {
|
||||||
|
if(source[i] != '\n') continue;
|
||||||
|
i += 1;
|
||||||
|
if(source[i] == '\t') return "\t";
|
||||||
|
var space_count: usize = 0;
|
||||||
|
while(i < source.len and source[i] == ' ') : (i += 1) {
|
||||||
|
space_count += 1;
|
||||||
|
}
|
||||||
|
if(source[i] == '\n') { // Some editors mess up indentation of empty lines
|
||||||
|
i -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(space_count == 0) continue;
|
||||||
|
if(source[i] == '/') continue; // Comments sometimes have additional alignment.
|
||||||
|
if(source[i] == '\\') continue; // multi-line strings might as well.
|
||||||
|
return source[i - space_count .. i];
|
||||||
|
}
|
||||||
|
return " " ** 4; // recommended style
|
||||||
|
}
|
||||||
|
|
||||||
// attempts to converts a slice of text into camelcase 'FUNCTION_NAME' -> 'functionName'
|
// attempts to converts a slice of text into camelcase 'FUNCTION_NAME' -> 'functionName'
|
||||||
fn createCamelcaseText(allocator: std.mem.Allocator, identifier: []const u8) ![]const u8 {
|
fn createCamelcaseText(allocator: std.mem.Allocator, identifier: []const u8) ![]const u8 {
|
||||||
// skip initial & ending underscores
|
// skip initial & ending underscores
|
||||||
@ -274,13 +295,26 @@ fn createCamelcaseText(allocator: std.mem.Allocator, identifier: []const u8) ![]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns a discard string `\n{indent}_ = identifier_name;`
|
// returns a discard string `\n{indent}_ = identifier_name;`
|
||||||
fn createDiscardText(allocator: std.mem.Allocator, identifier_name: []const u8, indent: usize) ![]const u8 {
|
fn createDiscardText(builder: *Builder, identifier_name: []const u8, declaration_start: usize, add_block_indentation: bool) ![]const u8 {
|
||||||
const new_text_len = 1 + indent + "_ = ;".len + identifier_name.len;
|
const indent = find_indent: {
|
||||||
|
const line = offsets.lineSliceUntilIndex(builder.handle.text, declaration_start);
|
||||||
|
for(line) |char, i| {
|
||||||
|
if(!std.ascii.isSpace(char)) {
|
||||||
|
break :find_indent line[0..i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break :find_indent line;
|
||||||
|
};
|
||||||
|
const additional_indent = if(add_block_indentation) detectIndentation(builder.handle.text) else "";
|
||||||
|
|
||||||
|
const allocator = builder.arena.allocator();
|
||||||
|
const new_text_len = 1 + indent.len + additional_indent.len + "_ = ;".len + identifier_name.len;
|
||||||
var new_text = try std.ArrayListUnmanaged(u8).initCapacity(allocator, new_text_len);
|
var new_text = try std.ArrayListUnmanaged(u8).initCapacity(allocator, new_text_len);
|
||||||
errdefer new_text.deinit(allocator);
|
errdefer new_text.deinit(allocator);
|
||||||
|
|
||||||
new_text.appendAssumeCapacity('\n');
|
new_text.appendAssumeCapacity('\n');
|
||||||
new_text.appendNTimesAssumeCapacity(' ', indent);
|
new_text.appendSliceAssumeCapacity(indent);
|
||||||
|
new_text.appendSliceAssumeCapacity(additional_indent);
|
||||||
new_text.appendSliceAssumeCapacity("_ = ");
|
new_text.appendSliceAssumeCapacity("_ = ");
|
||||||
new_text.appendSliceAssumeCapacity(identifier_name);
|
new_text.appendSliceAssumeCapacity(identifier_name);
|
||||||
new_text.appendAssumeCapacity(';');
|
new_text.appendAssumeCapacity(';');
|
||||||
|
Loading…
Reference in New Issue
Block a user