Fix cyclic dependency crash in GetRealUsedUnitsTransitive (#3419)
This commit is contained in:
parent
f61cd7770c
commit
0ffe331599
|
|
@ -542,47 +542,41 @@ namespace CodeCompletion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SymScope[] GetRealUsedUnitsTransitive(bool includeImplementationDependenciesForUnit = true)
|
public SymScope[] GetRealUsedUnitsTransitive(bool includeImplementationDependenciesForUnit = true)
|
||||||
{
|
{
|
||||||
var usedUnits = new List<SymScope>();
|
var unitsList = new List<SymScope>();
|
||||||
|
|
||||||
if (used_units != null)
|
HashSet<SymScope> visited = new HashSet<SymScope>();
|
||||||
{
|
|
||||||
usedUnits.AddRange(used_units.Where(unit => unit.file_name != null));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this is InterfaceUnitScope interfaceScope && includeImplementationDependenciesForUnit && interfaceScope.impl_scope != null)
|
void CollectUnitsHelper(SymScope currentScope)
|
||||||
{
|
{
|
||||||
foreach (var recursiveUsedUnit in interfaceScope.impl_scope.GetRealUsedUnitsTransitive(true))
|
IEnumerable<SymScope> usedUnitsLocal = currentScope.used_units?.Where(unit => unit.file_name != null);
|
||||||
|
|
||||||
|
foreach (var unit in usedUnitsLocal)
|
||||||
{
|
{
|
||||||
if (recursiveUsedUnit == this)
|
if (unitsList.Find(u => u.file_name == unit.file_name) == null)
|
||||||
continue;
|
unitsList.Add(unit);
|
||||||
|
}
|
||||||
|
|
||||||
if (usedUnits.FirstOrDefault(unit => unit.file_name == recursiveUsedUnit.file_name) == null)
|
if (currentScope is InterfaceUnitScope interfaceScope && includeImplementationDependenciesForUnit && interfaceScope.impl_scope != null)
|
||||||
|
{
|
||||||
|
CollectUnitsHelper(interfaceScope.impl_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var unit in usedUnitsLocal)
|
||||||
|
{
|
||||||
|
if (!visited.Contains(unit))
|
||||||
{
|
{
|
||||||
usedUnits.Add(recursiveUsedUnit);
|
visited.Add(unit);
|
||||||
|
CollectUnitsHelper(unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (used_units != null)
|
visited.Add(this);
|
||||||
{
|
CollectUnitsHelper(this);
|
||||||
foreach (var usedUnit in used_units)
|
|
||||||
{
|
|
||||||
var recursiveUsedUnits = usedUnit.GetRealUsedUnitsTransitive(includeImplementationDependenciesForUnit);
|
|
||||||
|
|
||||||
foreach (var recursiveUsedUnit in recursiveUsedUnits)
|
unitsList.Remove(this);
|
||||||
{
|
|
||||||
if (recursiveUsedUnit == this)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (usedUnits.FirstOrDefault(unit => unit.file_name == recursiveUsedUnit.file_name) == null)
|
return unitsList.ToArray();
|
||||||
{
|
|
||||||
usedUnits.Add(recursiveUsedUnit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return usedUnits.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual string GetFullName()
|
public virtual string GetFullName()
|
||||||
|
|
|
||||||
|
|
@ -165,42 +165,46 @@ namespace VisualPascalABC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (string FileName in filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
if (recomp_files.Count > 0)
|
||||||
{
|
{
|
||||||
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
foreach (string FileName in filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
|
|
||||||
if (dc != null)
|
|
||||||
{
|
{
|
||||||
CodeCompletion.SymScope watchedUnitScope = dc.visitor.entry_scope;
|
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
||||||
if (watchedUnitScope != null)
|
|
||||||
|
if (dc != null)
|
||||||
{
|
{
|
||||||
var usedUnitsTransitive = watchedUnitScope.GetRealUsedUnitsTransitive();
|
CodeCompletion.SymScope watchedUnitScope = dc.visitor.entry_scope;
|
||||||
|
if (watchedUnitScope != null)
|
||||||
for (int i = 0; i < usedUnitsTransitive.Length; i++)
|
|
||||||
{
|
{
|
||||||
string usedUnitFileName = usedUnitsTransitive[i].file_name;
|
var usedUnitsTransitive = watchedUnitScope.GetRealUsedUnitsTransitive();
|
||||||
|
|
||||||
// Если какая-то из зависимостей была перекомпилирована
|
for (int i = 0; i < usedUnitsTransitive.Length; i++)
|
||||||
if (recomp_files.Contains(usedUnitFileName))
|
|
||||||
{
|
{
|
||||||
// Помечаем нужные модули для будущей перекомпиляции
|
string usedUnitFileName = usedUnitsTransitive[i].file_name;
|
||||||
InvalidateDependentModules(usedUnitsTransitive, usedUnitFileName, filesToParse, FileName);
|
|
||||||
|
|
||||||
// Перекомпилируем текущий модуль
|
// Если какая-то из зависимостей была перекомпилирована
|
||||||
is_comp = true;
|
if (recomp_files.Contains(usedUnitFileName))
|
||||||
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, SourceFileOperation.GetText) as string;
|
|
||||||
|
|
||||||
// Здесь третий параметр false, потому что старые данные компиляции еще могут пригодиться до новой перекомпиляции EVA
|
|
||||||
if (CompileWatchedFile(FileName, text, false))
|
|
||||||
{
|
{
|
||||||
// успешная компиляция
|
// Помечаем нужные модули для будущей перекомпиляции
|
||||||
recomp_files.Add(FileName);
|
InvalidateDependentModules(usedUnitsTransitive, usedUnitFileName, filesToParse, FileName);
|
||||||
|
|
||||||
|
// Перекомпилируем текущий модуль
|
||||||
|
is_comp = true;
|
||||||
|
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, SourceFileOperation.GetText) as string;
|
||||||
|
|
||||||
|
// Здесь третий параметр false, потому что старые данные компиляции еще могут пригодиться до новой перекомпиляции EVA
|
||||||
|
if (CompileWatchedFile(FileName, text, false))
|
||||||
|
{
|
||||||
|
// успешная компиляция
|
||||||
|
recomp_files.Add(FileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_comp && mem_delta > 20000000 /*&& mem_delta > 10000000*/)
|
if (is_comp && mem_delta > 20000000 /*&& mem_delta > 10000000*/)
|
||||||
//postavil delta dlja pamjati, posle kototoj delaetsja sborka musora
|
//postavil delta dlja pamjati, posle kototoj delaetsja sborka musora
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -170,36 +170,39 @@ namespace VisualPascalABC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (string FileName in filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
if (recomp_files.Count > 0)
|
||||||
{
|
{
|
||||||
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
foreach (string FileName in filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
|
|
||||||
if (dc != null)
|
|
||||||
{
|
{
|
||||||
CodeCompletion.SymScope watchedUnitScope = dc.visitor.entry_scope;
|
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
||||||
if (watchedUnitScope != null)
|
|
||||||
|
if (dc != null)
|
||||||
{
|
{
|
||||||
var usedUnitsTransitive = watchedUnitScope.GetRealUsedUnitsTransitive();
|
CodeCompletion.SymScope watchedUnitScope = dc.visitor.entry_scope;
|
||||||
|
if (watchedUnitScope != null)
|
||||||
for (int i = 0; i < usedUnitsTransitive.Length; i++)
|
|
||||||
{
|
{
|
||||||
string usedUnitFileName = usedUnitsTransitive[i].file_name;
|
var usedUnitsTransitive = watchedUnitScope.GetRealUsedUnitsTransitive();
|
||||||
|
|
||||||
// Если какая-то из зависимостей была перекомпилирована
|
for (int i = 0; i < usedUnitsTransitive.Length; i++)
|
||||||
if (recomp_files.Contains(usedUnitFileName))
|
|
||||||
{
|
{
|
||||||
// Помечаем нужные модули для будущей перекомпиляции
|
string usedUnitFileName = usedUnitsTransitive[i].file_name;
|
||||||
InvalidateDependentModules(usedUnitsTransitive, usedUnitFileName, filesToParse, FileName);
|
|
||||||
|
|
||||||
// Перекомпилируем текущий модуль
|
// Если какая-то из зависимостей была перекомпилирована
|
||||||
is_comp = true;
|
if (recomp_files.Contains(usedUnitFileName))
|
||||||
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, SourceFileOperation.GetText) as string;
|
|
||||||
|
|
||||||
// Здесь третий параметр false, потому что старые данные компиляции еще могут пригодиться до новой перекомпиляции EVA
|
|
||||||
if (CompileWatchedFile(FileName, text, false))
|
|
||||||
{
|
{
|
||||||
// успешная компиляция
|
// Помечаем нужные модули для будущей перекомпиляции
|
||||||
recomp_files.Add(FileName);
|
InvalidateDependentModules(usedUnitsTransitive, usedUnitFileName, filesToParse, FileName);
|
||||||
|
|
||||||
|
// Перекомпилируем текущий модуль
|
||||||
|
is_comp = true;
|
||||||
|
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, SourceFileOperation.GetText) as string;
|
||||||
|
|
||||||
|
// Здесь третий параметр false, потому что старые данные компиляции еще могут пригодиться до новой перекомпиляции EVA
|
||||||
|
if (CompileWatchedFile(FileName, text, false))
|
||||||
|
{
|
||||||
|
// успешная компиляция
|
||||||
|
recomp_files.Add(FileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue