Skip to content

Commit 953462f

Browse files
committed
refactor declaration analyze
1 parent b20e064 commit 953462f

File tree

16 files changed

+657
-455
lines changed

16 files changed

+657
-455
lines changed
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
using EmmyLua.CodeAnalysis.Compilation.Declaration;
2+
using EmmyLua.CodeAnalysis.Compilation.Search;
3+
using EmmyLua.CodeAnalysis.Compilation.Type;
4+
using EmmyLua.CodeAnalysis.Document;
5+
using EmmyLua.CodeAnalysis.Document.Version;
6+
using EmmyLua.CodeAnalysis.Syntax.Node;
7+
using EmmyLua.CodeAnalysis.Syntax.Node.SyntaxNodes;
8+
9+
namespace EmmyLua.CodeAnalysis.Compilation.Analyzer.DeclarationAnalyzer;
10+
11+
public class AttachDeclarationAnalyzer(
12+
LuaDocument document,
13+
DeclarationContext declarationContext,
14+
SearchContext searchContext)
15+
{
16+
public void Analyze()
17+
{
18+
foreach (var (attachedElement, tagSyntaxes) in declarationContext.GetAttachedDocs())
19+
{
20+
AnalyzeGeneralDeclaration(attachedElement, tagSyntaxes);
21+
AnalyzeMethodDeclaration(attachedElement, tagSyntaxes);
22+
}
23+
}
24+
25+
private void AnalyzeGeneralDeclaration(LuaSyntaxElement attachedElement, List<LuaDocTagSyntax> docTagSyntaxes)
26+
{
27+
var declarations = FindDeclarations(attachedElement).ToList();
28+
foreach (var declaration in declarations)
29+
{
30+
foreach (var docTagSyntax in docTagSyntaxes)
31+
{
32+
switch (docTagSyntax)
33+
{
34+
case LuaDocTagDeprecatedSyntax:
35+
{
36+
declaration.Feature |= DeclarationFeature.Deprecated;
37+
break;
38+
}
39+
case LuaDocTagVisibilitySyntax visibilitySyntax:
40+
{
41+
declaration.Visibility =
42+
DeclarationWalker.DeclarationWalker.GetVisibility(visibilitySyntax.Visibility);
43+
break;
44+
}
45+
case LuaDocTagVersionSyntax versionSyntax:
46+
{
47+
var requiredVersions = new List<RequiredVersion>();
48+
foreach (var version in versionSyntax.Versions)
49+
{
50+
var action = version.Action;
51+
var framework = version.Version?.RepresentText ?? string.Empty;
52+
var versionNumber = version.VersionNumber?.Version ?? new VersionNumber(0, 0, 0, 0);
53+
requiredVersions.Add(new RequiredVersion(action, framework, versionNumber));
54+
}
55+
56+
declaration.RequiredVersions = requiredVersions;
57+
break;
58+
}
59+
case LuaDocTagNodiscardSyntax:
60+
{
61+
declaration.Feature |= DeclarationFeature.NoDiscard;
62+
break;
63+
}
64+
case LuaDocTagAsyncSyntax:
65+
{
66+
declaration.Feature |= DeclarationFeature.Async;
67+
break;
68+
}
69+
}
70+
}
71+
}
72+
73+
if (attachedElement is LuaLocalStatSyntax or LuaAssignStatSyntax or LuaTableFieldSyntax)
74+
{
75+
// general type define
76+
var nameTypeDefine = docTagSyntaxes.OfType<LuaDocTagNamedTypeSyntax>().FirstOrDefault();
77+
if (nameTypeDefine is { Name.RepresentText: { } name } &&
78+
declarations.FirstOrDefault() is { } firstDeclaration)
79+
{
80+
firstDeclaration.Info = firstDeclaration.Info with { DeclarationType = new LuaNamedType(name) };
81+
return;
82+
}
83+
84+
// general cast type
85+
var nameTypeList = docTagSyntaxes.OfType<LuaDocTagTypeSyntax>().FirstOrDefault();
86+
if (nameTypeList is { TypeList: { } typeList })
87+
{
88+
var luaTypeList = typeList.Select(searchContext.Infer).ToList();
89+
for (var i = 0; i < luaTypeList.Count; i++)
90+
{
91+
if (declarations.Count > i)
92+
{
93+
declarations[i].Info = declarations[i].Info with { DeclarationType = luaTypeList[i] };
94+
}
95+
}
96+
97+
return;
98+
}
99+
}
100+
}
101+
102+
private IEnumerable<LuaDeclaration> FindDeclarations(LuaSyntaxElement element)
103+
{
104+
switch (element)
105+
{
106+
case LuaLocalStatSyntax localStatSyntax:
107+
{
108+
foreach (var localName in localStatSyntax.NameList)
109+
{
110+
if (declarationContext.GetAttachedDeclaration(localName) is { } luaDeclaration)
111+
{
112+
yield return luaDeclaration;
113+
}
114+
}
115+
116+
break;
117+
}
118+
case LuaAssignStatSyntax assignStatSyntax:
119+
{
120+
foreach (var assign in assignStatSyntax.VarList)
121+
{
122+
if (declarationContext.GetAttachedDeclaration(assign) is { } luaDeclaration)
123+
{
124+
yield return luaDeclaration;
125+
}
126+
}
127+
128+
break;
129+
}
130+
case LuaTableFieldSyntax tableFieldSyntax:
131+
{
132+
if (declarationContext.GetAttachedDeclaration(tableFieldSyntax) is { } luaDeclaration)
133+
{
134+
yield return luaDeclaration;
135+
}
136+
137+
break;
138+
}
139+
case LuaFuncStatSyntax funcStatSyntax:
140+
{
141+
switch (funcStatSyntax)
142+
{
143+
case { IsLocal: true, LocalName.Name: { } name }:
144+
{
145+
if (declarationContext.GetAttachedDeclaration(funcStatSyntax.LocalName) is { } luaDeclaration)
146+
{
147+
yield return luaDeclaration;
148+
}
149+
150+
break;
151+
}
152+
case { IsLocal: false, NameExpr: { } nameExpr }:
153+
{
154+
if (declarationContext.GetAttachedDeclaration(nameExpr) is { } luaDeclaration)
155+
{
156+
yield return luaDeclaration;
157+
}
158+
159+
break;
160+
}
161+
case { IsMethod: true, IndexExpr: { } indexExpr }:
162+
{
163+
if (declarationContext.GetAttachedDeclaration(indexExpr) is { } luaDeclaration)
164+
{
165+
yield return luaDeclaration;
166+
}
167+
168+
break;
169+
}
170+
}
171+
172+
break;
173+
}
174+
default:
175+
{
176+
yield break;
177+
}
178+
}
179+
}
180+
181+
private record struct ParameterInfo(bool Nullable, LuaType Type);
182+
183+
private void AnalyzeMethodDeclaration(LuaSyntaxElement element, List<LuaDocTagSyntax> docTagSyntaxes)
184+
{
185+
var closureExpr = declarationContext.GetElementRelatedClosure(element);
186+
if (closureExpr is null)
187+
{
188+
return;
189+
}
190+
191+
var idType = declarationContext.Db.QueryTypeFromId(closureExpr.UniqueId);
192+
if (idType is not LuaMethodType methodType)
193+
{
194+
return;
195+
}
196+
197+
var genericParams = new List<LuaDeclaration>();
198+
var overloads = new List<LuaSignature>();
199+
var parameterDict = new Dictionary<string, ParameterInfo>();
200+
foreach (var docTagSyntax in docTagSyntaxes)
201+
{
202+
if (docTagSyntax is LuaDocTagOverloadSyntax overloadSyntax)
203+
{
204+
var func = searchContext.Infer(overloadSyntax.TypeFunc);
205+
if (func is LuaMethodType { MainSignature: { } mainSignature })
206+
{
207+
overloads.Add(mainSignature);
208+
}
209+
}
210+
else if (docTagSyntax is LuaDocTagGenericSyntax genericSyntax)
211+
{
212+
foreach (var param in genericSyntax.Params)
213+
{
214+
if (param is { Name: { } name })
215+
{
216+
var declaration = new LuaDeclaration(
217+
name.RepresentText,
218+
new GenericParamInfo(
219+
new(param),
220+
searchContext.Infer(param.Type)
221+
)
222+
);
223+
genericParams.Add(declaration);
224+
}
225+
}
226+
}
227+
else if (docTagSyntax is LuaDocTagParamSyntax paramSyntax)
228+
{
229+
if (paramSyntax.Name is { RepresentText: { } name })
230+
{
231+
var type = searchContext.Infer(paramSyntax.Type);
232+
var nullable = paramSyntax.Nullable;
233+
parameterDict[name] = new ParameterInfo(nullable, type);
234+
}
235+
else if (paramSyntax.VarArgs is not null)
236+
{
237+
var type = searchContext.Infer(paramSyntax.Type);
238+
parameterDict["..."] = new ParameterInfo(true, type);
239+
}
240+
}
241+
else if (docTagSyntax is LuaDocTagReturnSyntax returnSyntax)
242+
{
243+
var returnTypes = returnSyntax.TypeList.Select(searchContext.Infer).ToList();
244+
var returnType = returnTypes.Count switch
245+
{
246+
0 => Builtin.Nil,
247+
1 => returnTypes[0],
248+
_ => new LuaMultiReturnType(returnTypes)
249+
};
250+
methodType.MainSignature.ReturnType = returnType;
251+
}
252+
}
253+
254+
if (overloads.Count == 0)
255+
{
256+
overloads = null;
257+
}
258+
259+
var parameters = methodType.MainSignature.Parameters;
260+
foreach (var parameter in parameters)
261+
{
262+
if (parameter is LuaDeclaration { Name: { } name, Info: ParamInfo {} info } declaration)
263+
{
264+
if (parameterDict.TryGetValue(name, out var parameterInfo))
265+
{
266+
declaration.Info = info with
267+
{
268+
DeclarationType = parameterInfo.Type,
269+
Nullable = parameterInfo.Nullable,
270+
IsVararg = name == "..."
271+
};
272+
}
273+
}
274+
}
275+
276+
if (genericParams.Count > 0)
277+
{
278+
methodType = new LuaGenericMethodType(
279+
genericParams,
280+
new LuaSignature(methodType.MainSignature.ReturnType, parameters),
281+
overloads,
282+
methodType.ColonDefine);
283+
}
284+
else
285+
{
286+
methodType = new LuaMethodType(
287+
new LuaSignature(methodType.MainSignature.ReturnType, parameters),
288+
overloads,
289+
methodType.ColonDefine);
290+
}
291+
292+
declarationContext.Db.UpdateIdRelatedType(closureExpr.UniqueId, methodType);
293+
}
294+
}

EmmyLua/CodeAnalysis/Compilation/Analyzer/DeclarationAnalyzer/DeclarationAnalyzer.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ public class DeclarationAnalyzer(LuaCompilation compilation) : LuaAnalyzer(compi
66
{
77
public override void Analyze(AnalyzeContext analyzeContext)
88
{
9-
var searchContext = new SearchContext(compilation, new SearchContextFeatures() { Cache = false });
9+
var searchContext = new SearchContext(Compilation, new SearchContextFeatures() { Cache = false });
1010
foreach (var document in analyzeContext.LuaDocuments)
1111
{
12-
var declarationContext = new DeclarationContext(document.Id, this, analyzeContext);
12+
var declarationContext = new DeclarationContext(document, this, analyzeContext);
1313
var walker = new DeclarationWalker.DeclarationWalker(declarationContext, searchContext);
1414
document.SyntaxTree.SyntaxRoot.Accept(walker);
1515

@@ -18,6 +18,9 @@ public override void Analyze(AnalyzeContext analyzeContext)
1818
{
1919
Compilation.Db.AddDeclarationTree(document.Id, tree);
2020
}
21+
22+
var attachDeclarationAnalyzer = new AttachDeclarationAnalyzer(document, declarationContext, searchContext);
23+
attachDeclarationAnalyzer.Analyze();
2124
}
2225
}
2326
}

0 commit comments

Comments
 (0)