diff --git a/script/core/hint.lua b/script/core/hint.lua
index accb814921732b9d2de0d58341a879fc0e173648..62d2f7bfcda2e49a3bc6d419325cba68af7bbc50 100644
--- a/script/core/hint.lua
+++ b/script/core/hint.lua
@@ -6,7 +6,7 @@ local guide    = require 'parser.guide'
 local await    = require 'await'
 local define   = require 'proto.define'
 
-local function typeHint(uri, edits, start, finish)
+local function typeHint(uri, results, start, finish)
     local ast = files.getState(uri)
     if not ast then
         return
@@ -58,10 +58,11 @@ local function typeHint(uri, edits, start, finish)
             return
         end
         mark[src] = true
-        edits[#edits+1] = {
-            text   = view,
+        results[#results+1] = {
+            text   = ':' .. view,
             offset = src.finish,
             kind   = define.InlayHintKind.Type,
+            where  = 'right',
         }
     end)
 end
@@ -95,7 +96,7 @@ local function hasLiteralArgInCall(call)
     return false
 end
 
-local function paramName(uri, edits, start, finish)
+local function paramName(uri, results, start, finish)
     local paramConfig = config.get 'Lua.hint.paramName'
     if not paramConfig or paramConfig == 'None' then
         return
@@ -145,10 +146,11 @@ local function paramName(uri, edits, start, finish)
             and (paramConfig ~= 'Literal' or guide.isLiteral(arg)) then
                 mark[arg] = true
                 if args[i] and args[i] ~= '' then
-                    edits[#edits+1] = {
-                        text   = args[i],
+                    results[#results+1] = {
+                        text   = args[i] .. ':',
                         offset = arg.start,
                         kind   = define.InlayHintKind.Parameter,
+                        where  = 'left',
                     }
                 end
             end
@@ -157,8 +159,8 @@ local function paramName(uri, edits, start, finish)
 end
 
 return function (uri, start, finish)
-    local edits = {}
-    typeHint(uri, edits, start, finish)
-    paramName(uri, edits, start, finish)
-    return edits
+    local results = {}
+    typeHint(uri, results, start, finish)
+    paramName(uri, results, start, finish)
+    return results
 end
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index 4734686b703f7ebcf2a44700a67e8a8747b2016a..774e6c889a827821acc6f46445c2195db70de355 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -799,6 +799,28 @@ proto.on('textDocument/onTypeFormatting', function (params)
     return results
 end)
 
+proto.on('$/requestHint', function (params)
+    local core = require 'core.hint'
+    await.setID 'hint'
+    await.close 'hint'
+    if not config.get 'Lua.hint.enable' then
+        return
+    end
+    workspace.awaitReady()
+    local uri           = params.textDocument.uri
+    local start, finish = files.unrange(uri, params.range)
+    local results = core(uri, start, finish)
+    local hintResults = {}
+    for i, res in ipairs(results) do
+        hintResults[i] = {
+            text = res.text,
+            pos  = files.position(uri, res.offset, res.where),
+            kind = res.kind,
+        }
+    end
+    return hintResults
+end)
+
 -- Hint
 do
     local function updateHint(uri)
@@ -821,7 +843,7 @@ do
             if piece then
                 for _, edit in ipairs(piece) do
                     edits[#edits+1] = {
-                        newText = ':' .. edit.text,
+                        newText = edit.text,
                         range   = files.range(uri, edit.offset, edit.offset)
                     }
                 end