Skip to content
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
1 change: 1 addition & 0 deletions crates/emmylua_code_analysis/resources/std/builtin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
--- built-in type for Rawget
--- @alias std.RawGet<T, K> unknown

--- @deprecated use `const T` as a replacement, for example `---@generic const T`.
---
--- built-in type for generic template, for match integer const and true/false
--- @alias std.ConstTpl<T> unknown
Expand Down
14 changes: 7 additions & 7 deletions crates/emmylua_code_analysis/resources/std/global.lua
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ function rawequal(v1, v2) end
---
--- Gets the real value of `table[index]`, the `__index` metamethod. `table`
--- must be a table; `index` may be any value.
--- @generic T, K
--- @generic const T, const K
--- @param table T
--- @param index std.ConstTpl<K>
--- @param index K
--- @return std.RawGet<T, K>
function rawget(table, index) end

Expand Down Expand Up @@ -340,8 +340,8 @@ function require(modname) end
--- `index`. a negative number indexes from the end (-1 is the last argument).
--- Otherwise, `index` must be the string "#", and `select` returns
--- the total number of extra arguments it received.
--- @generic T, Num: integer | '#'
--- @param index std.ConstTpl<Num>
--- @generic T, const Num: integer | '#'
--- @param index Num
--- @param ... T...
--- @return std.Select<T..., Num>
function select(index, ...) end
Expand Down Expand Up @@ -460,9 +460,9 @@ function xpcall(f, msgh, ...) end

--- @version 5.1, JIT
---
--- @generic T, Start: integer, End: integer
--- @param i? std.ConstTpl<Start>
--- @param j? std.ConstTpl<End>
--- @generic const T, const Start: integer, const End: integer
--- @param i? Start
--- @param j? End
--- @param list T
--- @return std.Unpack<T, Start, End>
function unpack(list, i, j) end
Expand Down
6 changes: 3 additions & 3 deletions crates/emmylua_code_analysis/resources/std/table.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ function table.sort(list, comp) end
--- Returns the elements from the given list. This function is equivalent to
--- return `list[i]`, `list[i+1]`, `···`, `list[j]`
--- By default, i is 1 and j is #list.
--- @generic T, Start: integer, End: integer
--- @param i? std.ConstTpl<Start>
--- @param j? std.ConstTpl<End>
--- @generic const T, const Start: integer, const End: integer
--- @param i? Start
--- @param j? End
--- @param list T
--- @return std.Unpack<T, Start, End>
function table.unpack(list, i, j) end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,32 @@ use rowan::{TextRange, TextSize};
use smol_str::SmolStr;
use std::sync::Arc;

use crate::{GenericParam, GenericTpl, GenericTplId, LuaType};
use crate::{GenericParam, GenericTpl, GenericTplId};

pub trait GenericIndex: std::fmt::Debug {
fn add_generic_scope(&mut self, ranges: Vec<TextRange>, is_func: bool) -> GenericScopeId;

fn append_generic_param(&mut self, scope_id: GenericScopeId, param: GenericParam);
fn append_generic_param(
&mut self,
scope_id: GenericScopeId,
param: GenericParam,
) -> Option<GenericTplId>;

fn append_generic_params(&mut self, scope_id: GenericScopeId, params: Vec<GenericParam>) {
for param in params {
self.append_generic_param(scope_id, param);
let _ = self.append_generic_param(scope_id, param);
}
}

fn find_generic(
&self,
position: TextSize,
name: &str,
) -> Option<(GenericTplId, Option<LuaType>, Option<LuaType>)>;
fn find_generic(&self, position: TextSize, name: &str) -> Option<(GenericTplId, GenericParam)>;

fn generic_param_mut(&mut self, tpl_id: GenericTplId) -> Option<&mut GenericParam>;

fn mark_generic_const(&mut self, tpl_id: GenericTplId) -> Option<GenericParam> {
let param = self.generic_param_mut(tpl_id)?;
param.is_const = true;
Some(param.clone())
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -63,36 +71,38 @@ impl GenericIndex for FileGenericIndex {
scope_id
}

fn append_generic_param(&mut self, scope_id: GenericScopeId, param: GenericParam) {
fn append_generic_param(
&mut self,
scope_id: GenericScopeId,
param: GenericParam,
) -> Option<GenericTplId> {
if let Some(scope) = self.scopes.get_mut(scope_id.id) {
scope.insert_param(param);
}
}

fn append_generic_params(&mut self, scope_id: GenericScopeId, params: Vec<GenericParam>) {
for param in params {
self.append_generic_param(scope_id, param);
return Some(scope.insert_param(param));
}
None
}

/// Find generic parameter by position and name.
/// return (GenericTplId, constraint, default)
fn find_generic(
&self,
position: TextSize,
name: &str,
) -> Option<(GenericTplId, Option<LuaType>, Option<LuaType>)> {
fn find_generic(&self, position: TextSize, name: &str) -> Option<(GenericTplId, GenericParam)> {
for scope in self.scopes.iter().rev() {
if !scope.contains(position) {
continue;
}

if let Some((id, param)) = scope.params.get(name) {
return Some((
*id,
param.type_constraint.clone(),
param.default_type.clone(),
));
return Some((*id, param.clone()));
}
}

None
}

fn generic_param_mut(&mut self, tpl_id: GenericTplId) -> Option<&mut GenericParam> {
for scope in self.scopes.iter_mut().rev() {
for (id, param) in scope.params.values_mut() {
if *id == tpl_id {
return Some(param);
}
}
}

Expand Down Expand Up @@ -131,10 +141,11 @@ impl FileGenericScope {
self.next_tpl_id.is_func()
}

fn insert_param(&mut self, param: GenericParam) {
fn insert_param(&mut self, param: GenericParam) -> GenericTplId {
let tpl_id = self.next_tpl_id;
self.next_tpl_id = self.next_tpl_id.with_idx((tpl_id.get_idx() + 1) as u32);
self.params.insert(param.name.to_string(), (tpl_id, param));
tpl_id
}

fn contains(&self, position: TextSize) -> bool {
Expand Down Expand Up @@ -175,18 +186,19 @@ impl ConditionalInferIndex {

let tpl_id = GenericTplId::ConditionalInfer(self.next_infer_id);
self.next_infer_id += 1;
let param = GenericParam::new(SmolStr::new(name), None, None, false, None);
let tpl = Arc::new(GenericTpl::new(
tpl_id,
SmolStr::new(name).into(),
None,
None,
param.name.clone(),
param.constraint.clone(),
param.default.clone(),
param.is_const,
param.attributes.clone(),
));

let scope = &mut self.scopes[scope_idx];
scope.bindings.insert(name.to_string(), tpl.clone());
scope
.params
.push(GenericParam::new(SmolStr::new(name), None, None, None));
scope.params.push(param);
Some(tpl)
}

Expand Down
Loading
Loading