/// <summary>
        /// Perform constructor-specific completion
        /// </summary>
        private ValaCompletionDataList CompleteConstructor(string lineText, int line, int column)
        {
            ProjectInformation parser = Parser;
            Match match = initializationRegex.Match(lineText);
            ValaCompletionDataList list = new ValaCompletionDataList();

            ThreadPool.QueueUserWorkItem(delegate {
                if (match.Success)
                {
                    // variable initialization
                    if (match.Groups["typename"].Success || "var" != match.Groups["typename"].Value)
                    {
                        // simultaneous declaration and initialization
                        parser.GetConstructorsForType(match.Groups["typename"].Value, Document.FileName, line, column, list);
                    }
                    else if (match.Groups["variable"].Success)
                    {
                        // initialization of previously declared variable
                        parser.GetConstructorsForExpression(match.Groups["variable"].Value, Document.FileName, line, column, list);
                    }
                    if (0 == list.Count)
                    {
                        // Fallback to known types
                        parser.GetTypesVisibleFrom(Document.FileName, line, column, list);
                    }
                }
            });

            return(list);
        }        // CompleteConstructor
        /// <summary>
        /// Get the members of a symbol
        /// </summary>
        private ValaCompletionDataList GetMembersOfItem(string itemFullName, int line, int column)
        {
            ProjectInformation info = Parser;

            if (null == info)
            {
                return(null);
            }

            ValaCompletionDataList list = new ValaCompletionDataList();

            ThreadPool.QueueUserWorkItem(delegate {
                info.Complete(itemFullName, Document.FileName, line, column, list);
            });
            return(list);
        }
        /// <summary>
        /// Complete all symbols visible from a given location
        /// </summary>
        private ValaCompletionDataList GlobalComplete(CodeCompletionContext context)
        {
            ProjectInformation info = Parser;

            if (null == info)
            {
                return(null);
            }

            ValaCompletionDataList list = new ValaCompletionDataList();
            var loc = Editor.Document.OffsetToLocation(context.TriggerOffset);

            ThreadPool.QueueUserWorkItem(delegate {
                info.GetSymbolsVisibleFrom(Document.FileName, loc.Line + 1, loc.Column + 1, list);
            });
            return(list);
        }
        /// <summary>
        /// Complete all symbols visible from a given location
        /// </summary>
        private ValaCompletionDataList GlobalComplete(CodeCompletionContext context)
        {
            ProjectInformation info = Parser;

            if (null == info)
            {
                return(null);
            }

            ValaCompletionDataList list = new ValaCompletionDataList();
            int line, column;

            Editor.GetLineColumnFromPosition(context.TriggerOffset, out line, out column);
            ThreadPool.QueueUserWorkItem(delegate {
                info.GetSymbolsVisibleFrom(Document.FileName, line, column, list);
            });
            return(list);
        }
		public override ICompletionDataList HandleCodeCompletion (
		    CodeCompletionContext completionContext, char completionChar)
		{
			int line, column;
			string lineText = null;
			ProjectInformation parser = Parser;

			Editor.GetLineColumnFromPosition (completionContext.TriggerOffset, out line, out column);
			
			switch (completionChar) {
			case '.': // foo.[complete]
				lineText = Editor.GetLineText (line);
				if (column > lineText.Length){ column = lineText.Length; }
				lineText = lineText.Substring (0, column - 1);
				
				string itemName = GetTrailingSymbol (lineText);
				
				if (string.IsNullOrEmpty (itemName))
					return null;
				
				return GetMembersOfItem (itemName, line, column);
			case '\t':
			case ' ':
				lineText = Editor.GetLineText (line);
				if (column > lineText.Length){ column = lineText.Length; }
				lineText = lineText.Substring (0, column-1).Trim ();
				
				if (lineText.EndsWith ("new")) {
					return CompleteConstructor (lineText, line, column);
				} else if (lineText.EndsWith ("is")) {
					ValaCompletionDataList list = new ValaCompletionDataList ();
					ThreadPool.QueueUserWorkItem (delegate {
						parser.GetTypesVisibleFrom (Document.FileName, line, column, list);
					});
					return list;
				} else if (0 < lineText.Length) {
					char lastNonWS = lineText[lineText.Length-1];
					if (0 <= Array.IndexOf (operators, lastNonWS) || 
				          (1 == lineText.Length && 0 > Array.IndexOf (allowedChars, lastNonWS))) { 
						return GlobalComplete (completionContext); 
					}
				}
				
				break;
			default:
				if (0 <= Array.IndexOf (operators, completionChar)) {
					return GlobalComplete (completionContext);
				}
				break;
			}
			
			return null;
		}
		/// <summary>
		/// Complete all symbols visible from a given location
		/// </summary>
		private ValaCompletionDataList GlobalComplete (CodeCompletionContext context)
		{
			ProjectInformation info = Parser;
			if (null == info){ return null; }
			
			ValaCompletionDataList list = new ValaCompletionDataList ();
			int line, column;
			Editor.GetLineColumnFromPosition (context.TriggerOffset, out line, out column);
			ThreadPool.QueueUserWorkItem (delegate {
				info.GetSymbolsVisibleFrom (Document.FileName, line, column, list);
			});
			return list;
		}
		/// <summary>
		/// Get the members of a symbol
		/// </summary>
		private ValaCompletionDataList GetMembersOfItem (string itemFullName, int line, int column)
		{
			ProjectInformation info = Parser;
			if (null == info){ return null; }
			
			ValaCompletionDataList list = new ValaCompletionDataList ();
			ThreadPool.QueueUserWorkItem (delegate {
				info.Complete (itemFullName, Document.FileName, line, column, list);
			});
			return list;
		}
		/// <summary>
		/// Perform constructor-specific completion
		/// </summary>
		private ValaCompletionDataList CompleteConstructor (string lineText, int line, int column)
		{
			ProjectInformation parser = Parser;
			Match match = initializationRegex.Match (lineText);
			ValaCompletionDataList list = new ValaCompletionDataList ();
			
			ThreadPool.QueueUserWorkItem (delegate {
				if (match.Success) {
					// variable initialization
					if (match.Groups["typename"].Success || "var" != match.Groups["typename"].Value) {
						// simultaneous declaration and initialization
						parser.GetConstructorsForType (match.Groups["typename"].Value, Document.FileName, line, column, list);
					} else if (match.Groups["variable"].Success) {
						// initialization of previously declared variable
						parser.GetConstructorsForExpression (match.Groups["variable"].Value, Document.FileName, line, column, list);
					}
					if (0 == list.Count) { 
						// Fallback to known types
						parser.GetTypesVisibleFrom (Document.FileName, line, column, list);
					}
				}
			});
			
			return list;
		}// CompleteConstructor
		/// <summary>
		/// Complete all symbols visible from a given location
		/// </summary>
		private ValaCompletionDataList GlobalComplete (CodeCompletionContext context)
		{
			ProjectInformation info = Parser;
			if (null == info){ return null; }
			
			ValaCompletionDataList list = new ValaCompletionDataList ();
			var loc = Editor.Document.OffsetToLocation (context.TriggerOffset);
			ThreadPool.QueueUserWorkItem (delegate {
				info.GetSymbolsVisibleFrom (Document.FileName, loc.Line + 1, loc.Column + 1, list);
			});
			return list;
		}
        public override ICompletionDataList HandleCodeCompletion(
            CodeCompletionContext completionContext, char completionChar)
        {
            string             lineText = null;
            ProjectInformation parser   = Parser;
            var loc = Editor.Document.OffsetToLocation(completionContext.TriggerOffset);
            int line = loc.Line, column = loc.Column;

            switch (completionChar)
            {
            case '.':             // foo.[complete]
                lineText = Editor.GetLineText(line);
                if (column > lineText.Length)
                {
                    column = lineText.Length;
                }
                lineText = lineText.Substring(0, column - 1);

                string itemName = GetTrailingSymbol(lineText);

                if (string.IsNullOrEmpty(itemName))
                {
                    return(null);
                }

                return(GetMembersOfItem(itemName, line, column));

            case '\t':
            case ' ':
                lineText = Editor.GetLineText(line);
                if (0 == lineText.Length)
                {
                    return(null);
                }
                if (column > lineText.Length)
                {
                    column = lineText.Length;
                }
                lineText = lineText.Substring(0, column - 1).Trim();

                if (lineText.EndsWith("new"))
                {
                    return(CompleteConstructor(lineText, line, column));
                }
                else if (lineText.EndsWith("is"))
                {
                    ValaCompletionDataList list = new ValaCompletionDataList();
                    ThreadPool.QueueUserWorkItem(delegate {
                        parser.GetTypesVisibleFrom(Document.FileName, line, column, list);
                    });
                    return(list);
                }
                else if (0 < lineText.Length)
                {
                    char lastNonWS = lineText[lineText.Length - 1];
                    if (0 <= Array.IndexOf(operators, lastNonWS) ||
                        (1 == lineText.Length && 0 > Array.IndexOf(allowedChars, lastNonWS)))
                    {
                        return(GlobalComplete(completionContext));
                    }
                }

                break;

            default:
                if (0 <= Array.IndexOf(operators, completionChar))
                {
                    return(GlobalComplete(completionContext));
                }
                break;
            }

            return(null);
        }