internal IAnalysisResult TryGetUserDefinedType(string typeName, int index) { // do a binary search to determine what node we're in IAnalysisResult type = null; _body.SetNamespace(null); // TODO: need to handle multiple results of the same name AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (containingNode is IFunctionResult) { if ((containingNode as IFunctionResult).Types.TryGetValue(typeName, out type)) { return(type); } } if (_body is IModuleResult) { if ((_body as IModuleResult).Types.TryGetValue(typeName, out type) || (_body as IModuleResult).GlobalTypes.TryGetValue(typeName, out type)) { return(type); } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check global types if (modRes.GlobalTypes.TryGetValue(typeName, out type)) { return(type); } } } } } } return(type); }
public DropDownBarClient(IWpfTextView textView, IGeneroProjectEntry pythonProjectEntry) { _projectEntry = pythonProjectEntry; _projectEntry.OnNewParseTree += ParserOnNewParseTree; _textView = textView; _topLevelEntries = _nestedEntries = EmptyEntries; _dispatcher = Dispatcher.CurrentDispatcher; _textView.Caret.PositionChanged += CaretPositionChanged; }
internal void UpdateProjectEntry(IProjectEntry newEntry) { if (newEntry is IGeneroProjectEntry) { _projectEntry.OnNewParseTree -= ParserOnNewParseTree; _projectEntry = (IGeneroProjectEntry)newEntry; _projectEntry.OnNewParseTree += ParserOnNewParseTree; } }
internal static bool TryGetAnalysis(this ITextBuffer buffer, out IGeneroProjectEntry analysis) { IProjectEntry entry; if (buffer.TryGetAnalysis(out entry) && (analysis = entry as IGeneroProjectEntry) != null) { return(true); } analysis = null; return(false); }
public IGeneroProject AddImportedModule(string path, IGeneroProjectEntry importer) { IGeneroProject refProj = null; if (!ReferencedProjects.TryGetValue(path, out refProj)) { // need to tell the genero project analyzer to add a directory to the project refProj = VSGeneroPackage.Instance.DefaultAnalyzer.AddImportedProject(path, importer); if (refProj == null) { // TODO: need to report that the project is invalid? } else { ReferencedProjects.AddOrUpdate(path, refProj, (x, y) => y); } } return(refProj); }
/// <summary> /// Parses the specified file on disk. /// </summary> /// <param name="filename"></param> public void EnqueueFile(IProjectEntry projEntry, string filename) { var severity = Severity.Ignore; EnqueWorker(() => { for (int i = 0; i < 10; i++) { try { if (!File.Exists(filename)) { break; } using (var reader = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) { _parser.ParseFile(projEntry, filename, reader, severity); return; } } catch (IOException) { // file being copied, try again... Thread.Sleep(100); } catch (UnauthorizedAccessException) { // file is inaccessible, try again... Thread.Sleep(100); } } IGeneroProjectEntry gEntry = projEntry as IGeneroProjectEntry; IAnalysisCookie cookie = null; Genero4glAst node = null; if (gEntry != null) { // failed to parse, keep the UpdateTree calls balanced gEntry.UpdateTree(node, cookie); } }); }
public override IEnumerable <MemberResult> GetDefinedMembers(int index, AstMemberType memberType, bool isMemberAccess = false) { HashSet <MemberResult> members = new HashSet <MemberResult>(); HashSet <GeneroPackage> includedPackages = new HashSet <GeneroPackage>(); if (memberType.HasFlag(AstMemberType.SystemTypes) && !isMemberAccess) { // Built-in types members.AddRange(BuiltinTypes.Select(x => new MemberResult(Tokens.TokenKinds[x], GeneroMemberType.Keyword, this))); foreach (var package in Packages.Values.Where(x => _importedPackages[x.Name] && x.ContainsInstanceMembers && (this.LanguageVersion >= x.MinimumLanguageVersion && this.LanguageVersion <= x.MaximumLanguageVersion))) { members.Add(new MemberResult(package.Name, GeneroMemberType.Module, this)); includedPackages.Add(package); } } if (memberType.HasFlag(AstMemberType.Constants) && !isMemberAccess) { members.AddRange(SystemConstants.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Keyword, this))); members.AddRange(SystemMacros.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Variables) && !isMemberAccess) { members.AddRange(SystemVariables.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Keyword, this))); } if (memberType.HasFlag(AstMemberType.Functions) && !isMemberAccess) { members.AddRange(SystemFunctions.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Function, this))); foreach (var package in Packages.Values.Where(x => _importedPackages[x.Name] && x.ContainsStaticClasses && (this.LanguageVersion >= x.MinimumLanguageVersion && this.LanguageVersion <= x.MaximumLanguageVersion))) { if (!includedPackages.Contains(package)) { members.Add(new MemberResult(package.Name, GeneroMemberType.Module, this)); } } } // TODO: need to handle multiple results of the same name AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (containingNode is IFunctionResult) { if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange((containingNode as IFunctionResult).Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); foreach (var varList in (containingNode as IFunctionResult).LimitedScopeVariables) { foreach (var item in varList.Value) { if (item.Item2.IsInSpan(index)) { members.Add(new MemberResult(item.Item1.Name, item.Item1, GeneroMemberType.Instance, this)); break; } } } } if (memberType.HasFlag(AstMemberType.SystemTypes)) { members.AddRange((containingNode as IFunctionResult).Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange((containingNode as IFunctionResult).Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { foreach (var res in (containingNode as IFunctionResult).Variables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var varList in (containingNode as IFunctionResult).LimitedScopeVariables) { foreach (var item in varList.Value) { if (item.Item2.IsInSpan(index)) { members.Add(new MemberResult(item.Item1.Name, item.Item1, GeneroMemberType.Instance, this)); break; } } } } } if (_body is IModuleResult) { // check for module vars, types, and constants (and globals defined in this module) if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange((_body as IModuleResult).Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); members.AddRange((_body as IModuleResult).GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); } if (memberType.HasFlag(AstMemberType.UserDefinedTypes)) { members.AddRange((_body as IModuleResult).Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); members.AddRange((_body as IModuleResult).GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange((_body as IModuleResult).Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); members.AddRange((_body as IModuleResult).GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Dialogs)) { members.AddRange((_body as IModuleResult).Functions.Where(x => x.Value is DeclarativeDialogBlock) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Dialog, this))); members.AddRange((_body as IModuleResult).FglImports.Select(x => new MemberResult(x, GeneroMemberType.Module, this))); } if (memberType.HasFlag(AstMemberType.Reports)) { members.AddRange((_body as IModuleResult).Functions.Where(x => x.Value is ReportBlockNode) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Report, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { members.AddRange((_body as IModuleResult).Functions .Where(x => !(x.Value is ReportBlockNode) && !(x.Value is DeclarativeDialogBlock)) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Method, this))); foreach (var res in (_body as IModuleResult).Variables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var res in (_body as IModuleResult).GlobalVariables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } } // Tables and cursors are module specific, and cannot be accessed via fgl import if (memberType.HasFlag(AstMemberType.DeclaredCursors) || memberType.HasFlag(AstMemberType.PreparedCursors) || memberType.HasFlag(AstMemberType.Tables)) { if (memberType.HasFlag(AstMemberType.DeclaredCursors)) { members.AddRange((_body as IModuleResult).Cursors.Where(x => x.Value is DeclareStatement).Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.Cursor, this))); } if (memberType.HasFlag(AstMemberType.PreparedCursors)) { members.AddRange((_body as IModuleResult).Cursors.Where(x => x.Value is PrepareStatement).Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.Cursor, this))); } if (memberType.HasFlag(AstMemberType.Tables)) { members.AddRange((_body as IModuleResult).Tables.Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.DbTable, this))); } } else { members.AddRange((_body as IModuleResult).FglImports.Select(x => new MemberResult(x, GeneroMemberType.Module, this))); } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check global types // TODO: need to add an option to enable/disable legacy linking (to not reference other modules' non-public members if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange(modRes.GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); members.AddRange(modRes.Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); } if (memberType.HasFlag(AstMemberType.UserDefinedTypes)) { members.AddRange(modRes.GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); members.AddRange(modRes.Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange(modRes.GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); members.AddRange(modRes.Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Dialogs)) { members.AddRange(modRes.Functions.Where(x => x.Value is DeclarativeDialogBlock) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Dialog, this))); } if (memberType.HasFlag(AstMemberType.Reports)) { members.AddRange(modRes.Functions.Where(x => x.Value is ReportBlockNode) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Report, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { members.AddRange(modRes.Functions.Where(x => !(x.Value is ReportBlockNode) && !(x.Value is DeclarativeDialogBlock)) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Method, this))); foreach (var res in modRes.GlobalVariables/*.Where(x => * { * return x.Value.HasChildFunctions(this); * })*/ .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var res in modRes.Variables/*.Where(x => * { * return x.Value.HasChildFunctions(this); * })*/ .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } } } } } } } if (memberType.HasFlag(AstMemberType.Functions)) { _includePublicFunctions = true; // allow for deferred adding of public functions } if (memberType.HasFlag(AstMemberType.Tables)) { _includeDatabaseTables = true; // allow for deferred adding of external database tables } members.AddRange(this.ProjectEntry.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, memberType))); return(members); }
/// <summary> /// Gets the variables the given expression evaluates to. Variables include parameters, locals, and fields assigned on classes, modules and instances. /// /// Variables are classified as either definitions or references. Only parameters have unique definition points - all other types of variables /// have only one or more references. /// /// index is a 0-based absolute index into the file. /// </summary> public override IEnumerable <IAnalysisVariable> GetVariablesByIndex(string exprText, int index, IFunctionInformationProvider functionProvider, IDatabaseInformationProvider databaseProvider, IProgramFileProvider programFileProvider, bool isFunctionCallOrDefinition) { _functionProvider = functionProvider; _databaseProvider = databaseProvider; _programFileProvider = programFileProvider; List <IAnalysisVariable> vars = new List <IAnalysisVariable>(); _body.SetNamespace(null); AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (!isFunctionCallOrDefinition) { if (containingNode is IFunctionResult) { // Check for local vars, types, and constants IFunctionResult func = containingNode as IFunctionResult; IAnalysisResult res; if (func.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (func.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (func.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } List <Tuple <IAnalysisResult, IndexSpan> > limitedScopeVars; if (func.LimitedScopeVariables.TryGetValue(exprText, out limitedScopeVars)) { foreach (var item in limitedScopeVars) { if (item.Item2.IsInSpan(index)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Reference)); } } } } } if (_body is IModuleResult) { // check for module vars, types, and constants (and globals defined in this module) IModuleResult mod = _body as IModuleResult; IAnalysisResult res; if (!isFunctionCallOrDefinition) { if (mod.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalVariables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalTypes.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalConstants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } // check for cursors in this module if (mod.Cursors.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } } else { // check for module functions IFunctionResult funcRes; if (mod.Functions.TryGetValue(exprText, out funcRes)) { vars.Add(new AnalysisVariable(this.ResolveLocation(funcRes), VariableType.Definition, funcRes.Name, 1)); } } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (!isFunctionCallOrDefinition) { // check global vars, types, and constants // TODO: need to introduce option to enable/disable legacy linking IAnalysisResult res; if (modRes.GlobalVariables.TryGetValue(exprText, out res) || modRes.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } if (modRes.GlobalTypes.TryGetValue(exprText, out res) || modRes.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } if (modRes.GlobalConstants.TryGetValue(exprText, out res) || modRes.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } // check for cursors in this module if (modRes.Cursors.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } } else { // check for module functions IFunctionResult funcRes; if (modRes.Functions.TryGetValue(exprText, out funcRes)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(funcRes), VariableType.Definition, funcRes.Name, 1)); } } } } } } } /* TODO: * Need to check for: * 1) Temp tables * 2) DB Tables and columns * 3) Record fields */ if (isFunctionCallOrDefinition && _functionProvider != null) { var funcRes = _functionProvider.GetFunction(exprText); if (funcRes != null) { vars.AddRange(funcRes.Select(x => new AnalysisVariable(x.Location, VariableType.Definition, x.Name, 2))); } IFunctionResult funcResult; if (SystemFunctions.TryGetValue(exprText, out funcResult)) { vars.Add(new AnalysisVariable(funcResult.Location, VariableType.Definition, funcResult.Name, 2)); } } // try an imported module if (Body is IModuleResult && ProjectEntry != null) { if ((Body as IModuleResult).FglImports.Contains(exprText)) { // need to get the ast for the other project entry var refProjKVP = (ProjectEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileNameWithoutExtension(x.Directory); return(fn?.Equals(exprText, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { IGeneroProject definingProject = refProjKVP; vars.Add(new AnalysisVariable(new LocationInfo(definingProject.Directory, 1), VariableType.Definition)); } } } if (exprText.Contains('.') && vars.Count == 0) { IGeneroProject definingProj; IProjectEntry projEntry; bool dummyDef; IAnalysisResult res = GetValueByIndex(exprText, index, functionProvider, databaseProvider, _programFileProvider, isFunctionCallOrDefinition, out dummyDef, out definingProj, out projEntry); if (res != null) { LocationInfo locInfo = null; if (definingProj != null || projEntry != null) { locInfo = ResolveLocationInternal(definingProj, projEntry, res); } else { locInfo = this.ResolveLocation(res); } if (locInfo != null && ( (locInfo.Index > 0 || (locInfo.Line > 0 && locInfo.Column > 0)) || !string.IsNullOrWhiteSpace(locInfo.DefinitionURL) ) ) { vars.Add(new AnalysisVariable(locInfo, VariableType.Definition)); } } } if (_body is IModuleResult && _projEntry is IGeneroProjectEntry) { string dotPiece = exprText; string[] dotPieces = exprText.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (dotPieces.Length > 1) { dotPiece = dotPieces[0]; } if ((_body as IModuleResult).FglImports.Contains(dotPiece)) { // need to get the ast for the other project entry var refProjKVP = (_projEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileName(x.Directory); return(fn?.Equals(dotPiece, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { IProjectEntry dummyEntry; bool dummyDef; IAnalysisResult res = GetValueByIndex(exprText, index, functionProvider, databaseProvider, _programFileProvider, isFunctionCallOrDefinition, out dummyDef, out refProjKVP, out dummyEntry); if (res != null) { LocationInfo locInfo = null; locInfo = refProjKVP != null?ResolveLocationInternal(refProjKVP, dummyEntry, res) : this.ResolveLocation(res); if (locInfo != null && (locInfo.Index > 0 || (locInfo.Line > 0 && locInfo.Column > 0))) { vars.Add(new AnalysisVariable(locInfo, VariableType.Definition)); } } } } } if (!isFunctionCallOrDefinition) { foreach (var includeFile in this.ProjectEntry.GetIncludedFiles()) { IAnalysisResult res; if (includeFile.Analysis != null && includeFile.Analysis.Body is IModuleResult) { includeFile.Analysis.Body.SetNamespace(null); var mod = includeFile.Analysis.Body as IModuleResult; if (mod.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(ResolveLocationInternal(null, includeFile, res), VariableType.Definition)); } if (mod.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(ResolveLocationInternal(null, includeFile, res), VariableType.Definition)); } } } } return(vars); }
public static IAnalysisResult GetValueByIndex(string exprText, int index, Genero4glAst ast, out IGeneroProject definingProject, out IProjectEntry projectEntry, out bool isDeferredFunction, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false, bool getTypes = true, bool getVariables = true, bool getConstants = true) { isDeferredFunction = false; definingProject = null; projectEntry = null; //_functionProvider = functionProvider; //_databaseProvider = databaseProvider; //_programFileProvider = programFileProvider; AstNode containingNode = null; if (ast != null) { containingNode = GetContainingNode(ast.Body, index); ast.Body.SetNamespace(null); } IAnalysisResult res = null; int tmpIndex = 0; int bracketDepth = 0; bool doSearch = false; bool resetStartIndex = false; int startIndex = 0, endIndex = 0; bool noEndIndexSet = false; if (exprText == null) { return(null); } while (tmpIndex < exprText.Length) { if (resetStartIndex) { startIndex = tmpIndex; resetStartIndex = false; if (startIndex + 1 > exprText.Length) { break; } } doSearch = false; switch (exprText[tmpIndex]) { case '.': { if (bracketDepth == 0) { endIndex = tmpIndex - 1; if (endIndex >= startIndex) { // we have our 'piece' doSearch = true; } if (exprText[startIndex] == '.') { startIndex++; } } tmpIndex++; } break; case '[': if (noEndIndexSet) { noEndIndexSet = false; } else { if (bracketDepth == 0) { endIndex = tmpIndex - 1; } } bracketDepth++; tmpIndex++; break; case ']': { bracketDepth--; if (bracketDepth == 0) { if (exprText.Length <= tmpIndex + 1 || exprText[tmpIndex + 1] != '[') { // we have our first 'piece' doSearch = true; } else { noEndIndexSet = true; } } tmpIndex++; } break; default: { if (bracketDepth == 0 && (tmpIndex + 1 == exprText.Length)) { endIndex = tmpIndex; doSearch = true; } tmpIndex++; } break; } if (!doSearch) { continue; } // we can do our search var dotPiece = exprText.Substring(startIndex, (endIndex - startIndex) + 1); if (dotPiece.Contains('(')) { // remove the params piece int remIndex = dotPiece.IndexOf('('); dotPiece = dotPiece.Substring(0, remIndex); } bool lookForFunctions = isFunctionCallOrDefinition && (endIndex + 1 == exprText.Length); resetStartIndex = true; if (res != null) { if (ast != null) { var gmi = new GetMemberInput { Name = dotPiece, AST = ast, IsFunction = lookForFunctions }; IAnalysisResult tempRes = res.GetMember(gmi); if (gmi.DefiningProject != null && definingProject != gmi.DefiningProject) { definingProject = gmi.DefiningProject; } if (gmi.ProjectEntry != null && projectEntry != gmi.ProjectEntry) { projectEntry = gmi.ProjectEntry; } res = tempRes; if (tempRes == null) { res = null; break; } } else { res = null; break; } } else { IFunctionResult funcRes; if (!lookForFunctions) { if (SystemVariables.TryGetValue(dotPiece, out res) || SystemConstants.TryGetValue(dotPiece, out res) || SystemMacros.TryGetValue(dotPiece, out res)) { continue; } } else { if (SystemFunctions.TryGetValue(dotPiece, out funcRes)) { res = funcRes; continue; } if (ast != null && ast._functionProvider != null && ast._functionProvider.Name.Equals(dotPiece, StringComparison.OrdinalIgnoreCase)) { res = ast._functionProvider; continue; } } if (containingNode != null && containingNode is IFunctionResult) { IFunctionResult func = containingNode as IFunctionResult; if ((getVariables && func.Variables.TryGetValue(dotPiece, out res))) { continue; } if (!lookForFunctions) { // Check for local vars, types, and constants if ((getTypes && func.Types.TryGetValue(dotPiece, out res)) || (getConstants && func.Constants.TryGetValue(dotPiece, out res))) { continue; } List <Tuple <IAnalysisResult, IndexSpan> > limitedScopeVars; if ((getVariables && func.LimitedScopeVariables.TryGetValue(dotPiece, out limitedScopeVars))) { foreach (var item in limitedScopeVars) { if (item.Item2.IsInSpan(index)) { res = item.Item1; break; } } if (res != null) { continue; } } } } if (ast != null && ast.Body is IModuleResult) { IModuleResult mod = ast.Body as IModuleResult; if (!lookForFunctions) { // check for module vars, types, and constants (and globals defined in this module) if ((getVariables && (mod.Variables.TryGetValue(dotPiece, out res) || mod.GlobalVariables.TryGetValue(dotPiece, out res))) || (getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res)))) { continue; } // check for cursors in this module if (mod.Cursors.TryGetValue(dotPiece, out res)) { continue; } } else { // check for module functions if (mod.Functions.TryGetValue(dotPiece, out funcRes)) { // check for any function info collected at the project entry level, and update the function's documentation with that. if (ast._projEntry != null && ast._projEntry is IGeneroProjectEntry) { var commentInfo = (ast._projEntry as IGeneroProjectEntry).GetFunctionInfo(funcRes.Name); if (commentInfo != null) { funcRes.SetCommentDocumentation(commentInfo); } } res = funcRes; continue; } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (ast != null && ast.ProjectEntry != null && ast.ProjectEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = ast.ProjectEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { bool found = false; foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (!lookForFunctions) { // check global vars, types, and constants // TODO: need option to enable/disable legacy linking if ((getVariables && (modRes.Variables.TryGetValue(dotPiece, out res) || modRes.GlobalVariables.TryGetValue(dotPiece, out res))) || (getTypes && (modRes.Types.TryGetValue(dotPiece, out res) || modRes.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (modRes.Constants.TryGetValue(dotPiece, out res) || modRes.GlobalConstants.TryGetValue(dotPiece, out res)))) { found = true; break; } // check for cursors in this module if (modRes.Cursors.TryGetValue(dotPiece, out res)) { found = true; break; } } else { // check project functions if (modRes.Functions.TryGetValue(dotPiece, out funcRes)) { if (funcRes.AccessModifier == AccessModifier.Public) { res = funcRes; found = true; break; } } } } } } if (found) { continue; } } } // check for classes GeneroPackage package; if (Packages.TryGetValue(dotPiece, out package)) { res = package; continue; } /* TODO: * Need to check for: * 1) Temp tables */ // Nothing found yet... // If our containing node is at the function or globals level, we need to go deeper if (containingNode != null && (containingNode is GlobalsNode || containingNode is FunctionBlockNode || containingNode is ReportBlockNode)) { containingNode = GetContainingNode(containingNode, index); } // check for record field if (containingNode != null && (containingNode is DefineNode || containingNode is TypeDefNode)) { containingNode = GetContainingNode(containingNode, index); if (containingNode != null && (containingNode is VariableDefinitionNode || containingNode is TypeDefinitionNode) && containingNode.Children.Count == 1 && containingNode.Children[containingNode.Children.Keys[0]] is TypeReference) { var typeRef = containingNode.Children[containingNode.Children.Keys[0]] as TypeReference; while (typeRef != null && typeRef.Children.Count == 1) { if (typeRef.Children[typeRef.Children.Keys[0]] is RecordDefinitionNode) { var recNode = typeRef.Children[typeRef.Children.Keys[0]] as RecordDefinitionNode; VariableDef recField; if (recNode.MemberDictionary.TryGetValue(exprText, out recField)) { res = recField; break; } else { recField = recNode.MemberDictionary.Where(x => x.Value.LocationIndex < index) .OrderByDescending(x => x.Value.LocationIndex) .Select(x => x.Value) .FirstOrDefault(); if (recField != null) { typeRef = recField.Type; } else { break; } } } else if (typeRef.Children[typeRef.Children.Keys[0]] is TypeReference) { typeRef = typeRef.Children[typeRef.Children.Keys[0]] as TypeReference; } else { break; } } } } // try an imported module if (ast != null && ast.Body is IModuleResult && ast.ProjectEntry != null && ast.ProjectEntry != null) { if ((ast.Body as IModuleResult).FglImports.Contains(dotPiece)) { // need to get the ast for the other project entry var refProjKVP = (ast.ProjectEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileNameWithoutExtension(x.Directory); return(fn?.Equals(dotPiece, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { definingProject = refProjKVP; res = refProjKVP as IAnalysisResult; continue; } IAnalysisResult sysImportMod; // check the system imports if (SystemImportModules.TryGetValue(dotPiece, out sysImportMod)) { res = sysImportMod; continue; } } } if (!lookForFunctions) { // try include files var foundInclude = false; if (ast?.ProjectEntry != null) { foreach (var includeFile in ast.ProjectEntry.GetIncludedFiles()) { if (includeFile.Analysis?.Body is IModuleResult) { var mod = includeFile.Analysis.Body as IModuleResult; if ((getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res)))) { foundInclude = true; break; } } } } if (foundInclude) { continue; } if (ast?._databaseProvider != null) { res = ast._databaseProvider.GetTable(dotPiece); if (res != null) { continue; } } } // Only do a public function search if the dotPiece is the whole text we're searching for // I.e. no namespaces if (lookForFunctions && dotPiece == exprText) { if (searchInFunctionProvider == FunctionProviderSearchMode.Search) { if (res == null && ast?._functionProvider != null) { // check for the function name in the function provider var funcs = ast._functionProvider.GetFunction(dotPiece); if (funcs != null) { res = funcs.FirstOrDefault(); if (res != null) { continue; } } } } else if (searchInFunctionProvider == FunctionProviderSearchMode.Deferred) { isDeferredFunction = true; } } if (res == null) { break; } } } return(res); }
/// <summary> /// Gets information about the available signatures for the given expression. /// </summary> /// <param name="exprText">The expression to get signatures for.</param> /// <param name="index">The 0-based absolute index into the file.</param> public override IEnumerable <IFunctionResult> GetSignaturesByIndex(string exprText, int index, IReverseTokenizer revTokenizer, IFunctionInformationProvider functionProvider) { _functionProvider = functionProvider; // First see if we're in the process of defining a function List <MemberResult> dummyList; if (TryFunctionDefContext(index, revTokenizer, out dummyList)) { return(null); } /* * Need to check for: * 1) Functions within the current module * 2) Functions within the current project * 3) Public functions */ if (_body is IModuleResult) { _body.SetNamespace(null); // check for module vars, types, and constants (and globals defined in this module) IModuleResult mod = _body as IModuleResult; // check for module functions IFunctionResult funcRes; if (mod.Functions.TryGetValue(exprText, out funcRes)) { return(new IFunctionResult[1] { funcRes }); } } if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check project functions IFunctionResult funcRes; if (modRes.Functions.TryGetValue(exprText, out funcRes)) { if (funcRes.AccessModifier == AccessModifier.Public) { return new IFunctionResult[1] { funcRes } } ; } } } } } } // Check for class methods IGeneroProject dummyProj; IProjectEntry dummyProjEntry; bool dummyDef; IAnalysisResult member = GetValueByIndex(exprText, index, _functionProvider, _databaseProvider, _programFileProvider, true, out dummyDef, out dummyProj, out dummyProjEntry); if (member is IFunctionResult) { return(new IFunctionResult[1] { member as IFunctionResult }); } else if (member is VariableDef && (member as VariableDef).Type != null) { var typeRef = (member as VariableDef).Type; if (typeRef.ResolvedType != null && typeRef.ResolvedType is TypeDefinitionNode) { var tdn = typeRef.ResolvedType as TypeDefinitionNode; if (tdn.TypeRef != null && tdn.TypeRef is FunctionTypeReference) { return(new IFunctionResult[1] { tdn.TypeRef as FunctionTypeReference }); } } } if (_functionProvider != null) { // check for the function name in the function provider var func = _functionProvider.GetFunction(exprText); if (func != null) { return(func); } } return(null); }