diff --git a/src/analysis.zig b/src/analysis.zig index 63ba0cb..7940482 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -23,28 +23,65 @@ pub fn getFunctionByName(tree: *std.zig.ast.Tree, name: []const u8) ?*std.zig.as ///var comments = getFunctionDocComments(allocator, tree, func); ///defer if (comments) |comments_pointer| allocator.free(comments_pointer); ///``` -pub fn getFunctionDocComments(allocator: *std.mem.Allocator, tree: *std.zig.ast.Tree, func: *std.zig.ast.Node.FnProto) !?[]const u8 { - if (func.doc_comments) |doc_comments| { - var doc_it = doc_comments.lines.iterator(0); - var lines = std.ArrayList([]const u8).init(allocator); +pub fn getDocComments(allocator: *std.mem.Allocator, tree: *std.zig.ast.Tree, node: *std.zig.ast.Node) !?[]const u8 { + switch (node.id) { + .FnProto => { + const func = node.cast(std.zig.ast.Node.FnProto).?; + if (func.doc_comments) |doc_comments| { + var doc_it = doc_comments.lines.iterator(0); + var lines = std.ArrayList([]const u8).init(allocator); - while (doc_it.next()) |doc_comment| { - _ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..])); - } + while (doc_it.next()) |doc_comment| { + _ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..])); + } - return try std.mem.join(allocator, "\n", lines.toOwnedSlice()); - } else { - return null; + return try std.mem.join(allocator, "\n", lines.toOwnedSlice()); + } else { + return null; + } + }, + .VarDecl => { + const var_decl = node.cast(std.zig.ast.Node.VarDecl).?; + if (var_decl.doc_comments) |doc_comments| { + var doc_it = doc_comments.lines.iterator(0); + var lines = std.ArrayList([]const u8).init(allocator); + + while (doc_it.next()) |doc_comment| { + _ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..])); + } + + return try std.mem.join(allocator, "\n", lines.toOwnedSlice()); + } else { + return null; + } + }, + else => return null } } /// Gets a function signature (keywords, name, return value) pub fn getFunctionSignature(tree: *std.zig.ast.Tree, func: *std.zig.ast.Node.FnProto) []const u8 { - var start = tree.tokens.at(func.firstToken()).start; - var end = + const start = tree.tokens.at(func.firstToken()).start; + const end = if (func.body_node) |body| tree.tokens.at(body.firstToken()).start else tree.tokens.at(switch (func.return_type) { .Explicit, .InferErrorSet => |node| node.lastToken() }).end; return tree.source[start..end]; } + +/// Gets a function signature (keywords, name, return value) +pub fn getVariableSignature(tree: *std.zig.ast.Tree, var_decl: *std.zig.ast.Node.VarDecl) []const u8 { + const start = tree.tokens.at(var_decl.firstToken()).start; + const end = tree.tokens.at(var_decl.semicolon_token).start; + // var end = + // if (var_decl.init_n) |body| tree.tokens.at(body.firstToken()).start + // else tree.tokens.at(var_decl.name_token).end; + return tree.source[start..end]; +} + +// STYLE + +pub fn isCamelCase(name: []const u8) bool { + return !std.ascii.isUpper(name[0]) and std.mem.indexOf(u8, name, "_") == null; +} diff --git a/src/main.zig b/src/main.zig index f77e0ab..b355a2e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -111,6 +111,38 @@ pub fn publishDiagnostics(document: types.TextDocument) !void { // .relatedInformation = undefined }); } + } else { + var decls = tree.root_node.decls.iterator(0); + while (decls.next()) |decl_ptr| { + var decl = decl_ptr.*; + switch (decl.id) { + .FnProto => { + const func = decl.cast(std.zig.ast.Node.FnProto).?; + if (func.name_token) |name_token| { + const loc = tree.tokenLocation(0, name_token); + if (func.extern_export_inline_token == null and !analysis.isCamelCase(tree.tokenSlice(name_token))) { + try diagnostics.append(types.Diagnostic{ + .range = types.Range{ + .start = types.Position{ + .line = @intCast(i64, loc.line), + .character = @intCast(i64, loc.column) + }, + .end = types.Position{ + .line = @intCast(i64, loc.line), + .character = @intCast(i64, loc.column) + } + }, + .severity = types.DiagnosticSeverity.Information, + .code = "BadStyle", + .source = "zls", + .message = "Callables should be camelCase" + }); + } + } + }, + else => {} + } + } } try send(types.Notification{ @@ -140,11 +172,7 @@ pub fn completeGlobal(id: i64, document: types.TextDocument) !void { switch (decl.id) { .FnProto => { const func = decl.cast(std.zig.ast.Node.FnProto).?; - var doc_comments = try analysis.getFunctionDocComments(allocator, tree, func); - // defer if (doc_comments) |dc| allocator.free(dc); - // var abc = "abc"; - // try log("{}", .{abc}); - // if (std.mem.eql(u8, tree.tokenSlice(func.name_token.?), name)) return func; + var doc_comments = try analysis.getDocComments(allocator, tree, decl); var doc = types.MarkupContent{ .kind = types.MarkupKind.Markdown, .value = doc_comments orelse "" @@ -157,11 +185,17 @@ pub fn completeGlobal(id: i64, document: types.TextDocument) !void { }); }, .VarDecl => { - const vari = decl.cast(std.zig.ast.Node.VarDecl).?; - // if (std.mem.eql(u8, tree.tokenSlice(func.name_token.?), name)) return func; + const var_decl = decl.cast(std.zig.ast.Node.VarDecl).?; + var doc_comments = try analysis.getDocComments(allocator, tree, decl); + var doc = types.MarkupContent{ + .kind = types.MarkupKind.Markdown, + .value = doc_comments orelse "" + }; try completions.append(types.CompletionItem{ - .label = tree.tokenSlice(vari.name_token), + .label = tree.tokenSlice(var_decl.name_token), .kind = types.CompletionItemKind.Variable, + .documentation = doc, + .detail = analysis.getVariableSignature(tree, var_decl) }); }, else => {}