public static IEnumerable<ICompletionData> DoCodeComplete(string editorText, int offset) // not the best way to put in the whole string every time
        {
            var doc = new ReadOnlyDocument(editorText);
            var location = doc.GetLocation(offset);

            string parsedText = editorText; // TODO: Why are there different values in test cases?


            var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs");
            syntaxTree.Freeze();
            var unresolvedFile = syntaxTree.ToTypeSystem();

            var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);

            IProjectContent pctx = new CSharpProjectContent();
            var refs = new List<IUnresolvedAssembly> { mscorlib.Value, systemCore.Value, systemAssembly.Value };
            pctx = pctx.AddAssemblyReferences(refs);
            pctx = pctx.AddOrUpdateFiles(unresolvedFile);

            var cmp = pctx.CreateCompilation();

            var resolver3 = unresolvedFile.GetResolver(cmp, location);
            var engine = new CSharpCompletionEngine(doc, mb, new TestCompletionDataFactory(resolver3), pctx, resolver3.CurrentTypeResolveContext);


            engine.EolMarker = Environment.NewLine;
            engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();

            var data = engine.GetCompletionData(offset, controlSpace: false);
            return data;

        }
		public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, ICodeContext context)
		{
			if (context == null)
				throw new ArgumentNullException("context");
			string content = GeneratePartialClassContextStub(context);
			const string caretPoint = "$__Caret_Point__$;";
			int caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length;
			SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$"));
			var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete));
			return new CSharpCompletionBinding(context, doc.GetLocation(caretOffset), doc.CreateSnapshot());
		}
		public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context)
		{
			var lang = SD.LanguageService.GetLanguageByFileName(context.FileName);
			if (lang == null)
				return null;
			string content = GeneratePartialClassContextStub(context);
			const string caretPoint = "$__Caret_Point__$;";
			int caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length;
			SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$"));
			var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete));
			return lang.CreateCompletionBinding(context.FileName, doc.GetLocation(caretOffset), doc.CreateSnapshot());
		}
Example #4
0
		public static void Roundtrip(CSharpParser parser, string fileName, string code)
		{
			// 1. Parse
			CompilationUnit cu = parser.Parse(code, fileName);
			if (parser.HasErrors)
				throw new InvalidOperationException("There were parse errors.");
			
			// 2. Output
			StringWriter w = new StringWriter();
			cu.AcceptVisitor(new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ()));
			string generatedCode = w.ToString().TrimEnd();
			
			// 3. Compare output with original (modulo whitespaces)
			int pos2 = 0;
			for (int pos1 = 0; pos1 < code.Length; pos1++) {
				if (!char.IsWhiteSpace(code[pos1])) {
					while (pos2 < generatedCode.Length && char.IsWhiteSpace(generatedCode[pos2]))
						pos2++;
					if (pos2 >= generatedCode.Length || code[pos1] != generatedCode[pos2]) {
						ReadOnlyDocument doc = new ReadOnlyDocument(code);
						File.WriteAllText(Path.Combine(Program.TempPath, "roundtrip-error.cs"), generatedCode);
						throw new InvalidOperationException("Mismatch at " + doc.GetLocation(pos1) + " of file " + fileName);
					}
					pos2++;
				}
			}
			if (pos2 != generatedCode.Length)
				throw new InvalidOperationException("Mismatch at end of file " + fileName);
			
			// 3b - validate that there are no lone \r
			if (generatedCode.Replace(w.NewLine, "\n").IndexOf('\r') >= 0)
				throw new InvalidOperationException(@"Got lone \r in " + fileName);
			
			// 4. Parse generated output
			CompilationUnit generatedCU;
			try {
				generatedCU = parser.Parse(generatedCode, fileName);
			} catch {
				File.WriteAllText(Path.Combine(Program.TempPath, "roundtrip-error.cs"), generatedCode, Encoding.Unicode);
				throw;
			}
			
			if (parser.HasErrors) {
				File.WriteAllText(Path.Combine(Program.TempPath, "roundtrip-error.cs"), generatedCode);
				throw new InvalidOperationException("There were parse errors in the roundtripped " + fileName);
			}
			
			// 5. Compare AST1 with AST2
			if (!cu.IsMatch(generatedCU))
				throw new InvalidOperationException("AST match failed for " + fileName + ".");
		}
Example #5
0
		public static XamlUnresolvedFile Create(FileName fileName, ITextSource fileContent, AXmlDocument document)
		{
			XamlUnresolvedFile file = new XamlUnresolvedFile(fileName);
			ReadOnlyDocument textDocument = new ReadOnlyDocument(fileContent, fileName);
			
			file.errors.AddRange(document.SyntaxErrors.Select(err => new Error(ErrorType.Error, err.Description, textDocument.GetLocation(err.StartOffset))));
			var visitor = new XamlDocumentVisitor(file, textDocument);
			visitor.VisitDocument(document);
			if (visitor.TypeDefinition != null)
				file.topLevel = new[] { visitor.TypeDefinition };
			else
				file.topLevel = new IUnresolvedTypeDefinition[0];
			
			return file;
		}
Example #6
0
		public void EmptyReadOnlyDocument()
		{
			IDocument document = new ReadOnlyDocument(string.Empty);
			Assert.AreEqual(string.Empty, document.Text);
			Assert.AreEqual(0, document.TextLength);
			Assert.AreEqual(1, document.LineCount);
			Assert.AreEqual(0, document.GetOffset(1, 1));
			Assert.AreEqual(new TextLocation(1, 1), document.GetLocation(0));
			
			Assert.AreEqual(0, document.GetLineByNumber(1).Offset);
			Assert.AreEqual(0, document.GetLineByNumber(1).EndOffset);
			Assert.AreEqual(0, document.GetLineByNumber(1).Length);
			Assert.AreEqual(0, document.GetLineByNumber(1).TotalLength);
			Assert.AreEqual(0, document.GetLineByNumber(1).DelimiterLength);
			Assert.AreEqual(1, document.GetLineByNumber(1).LineNumber);
		}
		static CompletionDataList CreateProvider (string text, bool isCtrlSpace)
		{
			string parsedText;
			string editorText;
			int cursorPosition = text.IndexOf ('$');
			int endPos = text.IndexOf ('$', cursorPosition + 1);
			if (endPos == -1) {
				parsedText = editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1);
			} else {
				parsedText = text.Substring (0, cursorPosition) + new string (' ', endPos - cursorPosition) + text.Substring (endPos + 1);
				editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring (endPos + 1);
				cursorPosition = endPos - 1; 
			}
			var doc = new ReadOnlyDocument (editorText);
			
			IProjectContent pctx = new CSharpProjectContent ();
			pctx = pctx.AddAssemblyReferences (new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
			
			var compilationUnit = new CSharpParser ().Parse (parsedText, "program.cs");
			compilationUnit.Freeze ();
			
			var parsedFile = compilationUnit.ToTypeSystem ();
			pctx = pctx.UpdateProjectContent (null, parsedFile);
			
			var cmp = pctx.CreateCompilation ();
			var loc = doc.GetLocation (cursorPosition);
			
			var rctx = new CSharpTypeResolveContext (cmp.MainAssembly);
			rctx = rctx.WithUsingScope (parsedFile.GetUsingScope (loc).Resolve (cmp));
			

			var curDef = parsedFile.GetInnermostTypeDefinition (loc);
			if (curDef != null) {
				var resolvedDef = curDef.Resolve (rctx).GetDefinition ();
				rctx = rctx.WithCurrentTypeDefinition (resolvedDef);
				var curMember = resolvedDef.Members.FirstOrDefault (m => m.Region.Begin <= loc && loc < m.BodyRegion.End);
				if (curMember != null)
					rctx = rctx.WithCurrentMember (curMember);
			}
			var engine = new CSharpCompletionEngine (doc, new TestFactory (), pctx, rctx, compilationUnit, parsedFile);
				
			engine.EolMarker = Environment.NewLine;
			engine.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
			
			var data = engine.GetCompletionData (cursorPosition, isCtrlSpace);
			
			return new CompletionDataList () {
				Data = data,
				AutoCompleteEmptyMatch = engine.AutoCompleteEmptyMatch,
				AutoSelect = engine.AutoSelect,
				DefaultCompletionString = engine.DefaultCompletionString
			};
		}
        public static ProjectAnalysisResult RunFullProjectAnalysis(ProjectAnalysisRequest projectAnalysisRequest) // ProjectModel projectModel, int fileId, int line, int column)
        {
            Stopwatch sw = Stopwatch.StartNew();

            ProjectAnalysisResult projectAnalysisResult = new ProjectAnalysisResult();
            ProjectModel projectModel = projectAnalysisRequest.ProjectModel;


            // Set up the project (if not already done)
            if (projectModel.ProjectContent == null)
            {
                projectModel.ProjectContent = new CSharpProjectContent();
                projectModel.ProjectContent = projectModel.ProjectContent.AddAssemblyReferences(QCReferences.Value);
            }

            // For each new file, we need to integrate it into the project content
            var fileModelsInProject = projectModel.GetFileDescendants().ToArray();
            foreach (var fileModelInProject in fileModelsInProject)
            {
                IntegrateFileModel(projectModel, fileModelInProject);
            }

            // We can return now if no code completion was requested
            if (projectAnalysisRequest.CodeCompletionParameters == null)
            {
                projectAnalysisResult.TimeElapsed = sw.Elapsed;
                return projectAnalysisResult;
            }

            // Now it's time to give attention specifically to the matter of resolving the code completion
            // options.  This, of course, requires a deeper analysis of the specified file...
            
            var codeCompletionParams = projectAnalysisRequest.CodeCompletionParameters;

            // Locate the file in the project
            ProjectFileModel fileModel = projectModel.FindFile(codeCompletionParams.FileId);
            if (fileModel == null)
                throw new Exception("Specified file does not exist in this project");
            

            // Create a TypeSystem.ICompilation that allows resolving within the project.
            var compilation = projectModel.ProjectContent.CreateCompilation();

            #region Resolve text cursor/caret location
            
            // The text cursor position is crucial to creating a properly-scoped type resolution context
            // so as to get relevant code completion suggestions.
            int textCursorOffset;
            TextLocation textCursorLocation;
            ReadOnlyDocument doc = new ReadOnlyDocument(fileModel.Content);
            if (codeCompletionParams.Line == 0 && codeCompletionParams.Column == 0)
            {
                textCursorOffset = codeCompletionParams.Offset;
                textCursorLocation = doc.GetLocation(textCursorOffset);
                codeCompletionParams.Line = textCursorLocation.Line;
                codeCompletionParams.Column = textCursorLocation.Column;
            }
            else
            {
                textCursorLocation = new TextLocation(codeCompletionParams.Line, codeCompletionParams.Column);
                textCursorOffset = doc.GetOffset(textCursorLocation);
                codeCompletionParams.Offset = textCursorOffset;
            }

            #endregion

            #region Create and Refine the type resolution context as much as possible based upon the cursor position

            var typeResolveContext = new CSharpTypeResolveContext(compilation.MainAssembly);
            // Constrain the resolve context by using scope
            typeResolveContext = typeResolveContext
                .WithUsingScope(fileModel.UnresolvedFile.GetUsingScope(textCursorLocation)
                .Resolve(compilation));

            var curDef = fileModel.UnresolvedFile.GetInnermostTypeDefinition(textCursorLocation);
            if (curDef != null)
            {
                var resolvedDef = curDef.Resolve(typeResolveContext).GetDefinition();
                typeResolveContext = typeResolveContext.WithCurrentTypeDefinition(resolvedDef);
                var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= textCursorLocation && textCursorLocation < m.BodyRegion.End);
                if (curMember != null)
                {
                    typeResolveContext = typeResolveContext.WithCurrentMember(curMember);
                }
            }

            #endregion

            // The purpose of the rest of these steps is a little fuzzy in my mind...  
            // I'm still trying to understand them fully and if/why they're all needed.
            // It seems there is some redundancy here...

            var completionContext = new DefaultCompletionContextProvider(doc, fileModel.UnresolvedFile);

            #region Add Preprocessor Symbols??
            completionContext.AddSymbol("TEST");
            foreach (var sym in fileModel.SyntaxTree.ConditionalSymbols)
                completionContext.AddSymbol(sym);
            #endregion

            var completionDataFactory = new TestCompletionDataFactory(new CSharpResolver(typeResolveContext));
            
            var completionEngine = new CSharpCompletionEngine(doc, completionContext, completionDataFactory, projectModel.ProjectContent, typeResolveContext);
            completionEngine.EolMarker = Environment.NewLine;
            completionEngine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
            projectModel.CompletionEngine = completionEngine;

#region Debugging Aid
            // Resolve content around text cursor
            int numberOfCharactersAroundCursorToResolve = 20;
            int firstCharOffset = textCursorOffset - numberOfCharactersAroundCursorToResolve/2;
            if (firstCharOffset < 0)
                firstCharOffset = 0;
            if (doc.TextLength < firstCharOffset+numberOfCharactersAroundCursorToResolve)
                numberOfCharactersAroundCursorToResolve = doc.TextLength - firstCharOffset;
            string surroundingText = doc.GetText(firstCharOffset, numberOfCharactersAroundCursorToResolve);
            Debug.WriteLine("Text around cursor: [{0}]", surroundingText);
#endregion

            // Finally, generate completion data!
            var completionOptions = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();
            projectAnalysisResult.CompletionOptions = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();
            projectAnalysisResult.AutoCompleteEmptyMatch = completionEngine.AutoCompleteEmptyMatch;
            projectAnalysisResult.AutoSelect = completionEngine.AutoSelect;
            projectAnalysisResult.DefaultCompletionString = completionEngine.DefaultCompletionString;

            int startPos, wordLength;
            if (completionEngine.TryGetCompletionWord(textCursorOffset, out startPos, out wordLength))
            {
                Debug.WriteLine("TryGetCompletionWord :: startpos:{0}  wordlength:{1}", startPos, wordLength);
                projectAnalysisResult.CompletionWord = doc.GetText(startPos, wordLength);
            }

            projectAnalysisResult.TimeElapsed = sw.Elapsed;

            return projectAnalysisResult;
        }
		public static CSharpCompletionEngine CreateEngine(string text, out int cursorPosition, params IUnresolvedAssembly[] references)
		{
			string parsedText;
			string editorText;
			var selectionStart = text.IndexOf('$');
			cursorPosition = selectionStart;
			int endPos = text.IndexOf('$', cursorPosition + 1);
			if (endPos == -1) {
				parsedText = editorText = cursorPosition < 0 ? text : text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1);
			} else {
				parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1);
				editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1);
				cursorPosition = endPos - 1; 
			}
			var doc = new ReadOnlyDocument(editorText);

			IProjectContent pctx;
			SyntaxTree syntaxTree;
			CSharpUnresolvedFile unresolvedFile;
			CreateCompilation (parsedText, out pctx, out syntaxTree, out unresolvedFile, true, references);
			var cmp = pctx.CreateCompilation();

			var loc = cursorPosition > 0 ? doc.GetLocation(selectionStart) : new TextLocation (1, 1);

			var rctx = new CSharpTypeResolveContext(cmp.MainAssembly);
			rctx = rctx.WithUsingScope(unresolvedFile.GetUsingScope(loc).Resolve(cmp));

			var curDef = unresolvedFile.GetInnermostTypeDefinition(loc);
			if (curDef != null) {
				var resolvedDef = curDef.Resolve(rctx).GetDefinition();
				rctx = rctx.WithCurrentTypeDefinition(resolvedDef);
				var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= loc && loc < m.BodyRegion.End);
				if (curMember != null) {
					rctx = rctx.WithCurrentMember(curMember);
				}
			}
			var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
			mb.AddSymbol ("TEST");
			foreach (var sym in syntaxTree.ConditionalSymbols) {
				mb.AddSymbol(sym);
			}
			var engine = new CSharpCompletionEngine(doc, mb, new TestFactory(new CSharpResolver (rctx)), pctx, rctx);
			engine.AutomaticallyAddImports = true;
			engine.EolMarker = Environment.NewLine;
			engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
			return engine;
		}
Example #10
0
		internal static IParameterDataProvider CreateProvider (string text)
		{
			string parsedText;
			string editorText;
			int cursorPosition = text.IndexOf ('$');
			int endPos = text.IndexOf ('$', cursorPosition + 1);
			if (endPos == -1)
				parsedText = editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1);
			else {
				parsedText = text.Substring (0, cursorPosition) + new string (' ', endPos - cursorPosition) + text.Substring (endPos + 1);
				editorText = text.Substring (0, cursorPosition) + text.Substring (cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring (endPos + 1);
				cursorPosition = endPos - 1; 
			}
			var doc = new ReadOnlyDocument (editorText);
			
			IProjectContent pctx = new CSharpProjectContent ();
			pctx = pctx.AddAssemblyReferences (new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
			
			var compilationUnit = new CSharpParser ().Parse (parsedText, "program.cs");
			
			var parsedFile = compilationUnit.ToTypeSystem ();
			pctx = pctx.UpdateProjectContent (null, parsedFile);
			var cmp = pctx.CreateCompilation ();
			var loc = doc.GetLocation (cursorPosition);
			
			var engine = new CSharpParameterCompletionEngine (doc, new TestFactory (pctx));
			
			var rctx = new CSharpTypeResolveContext (cmp.MainAssembly);
			rctx = rctx.WithUsingScope (parsedFile.GetUsingScope (loc).Resolve (cmp));
			var curDef = parsedFile.GetInnermostTypeDefinition (loc);
			if (curDef != null) {
				rctx = rctx.WithCurrentTypeDefinition (curDef.Resolve (rctx).GetDefinition ());
				var curMember = parsedFile.GetMember (loc);
				if (curMember != null)
					rctx = rctx.WithCurrentMember (curMember.CreateResolved (rctx));
			}
			engine.ctx = rctx;
			
			engine.CSharpParsedFile = parsedFile;
			engine.ProjectContent = pctx;
			engine.Unit = compilationUnit;
			
			return engine.GetParameterDataProvider (cursorPosition, doc.GetCharAt (cursorPosition - 1));
		}
        //// todo: eliminate this method later
        //private static void AugmentProjectModelWithAlgorithmBase(ProjectModel model)
        //{
        //    model.Children.Add(QcAlgorithmFileModel.Value);
        //}

        public static ProjectAnalysisResult RunFullProjectAnalysis(ProjectAnalysisRequest projectAnalysisRequest)
        {
            Stopwatch sw = Stopwatch.StartNew();

            ProjectAnalysisResult projectAnalysisResult = new ProjectAnalysisResult();
            ProjectModel projectModel = projectAnalysisRequest.ProjectModel;

            // todo: Ask Jared why QCAlgorithm is a partial class and why it's not included in "common"

#if false
            // ************************************************************************************
            // NOTE:  In order to get this project building cleanly, with minimal dependencies 
            // before checking into Github, I've removed all hard QuantConnect dependencies,
            // including the QCAlgorithm.cs embedded resource and the assembly references to 
            // QuantConnect.Algorithm.Interface

            // Augment the project model with the QCAgorithm base class
            // projectModel.Children.Add(QcAlgorithmFileModel.Value);
            
            // ************************************************************************************
#endif

            // Set up the project (if not already done)
            if (projectModel.ProjectContent == null)
            {
                projectModel.ProjectContent = new CSharpProjectContent();
                projectModel.ProjectContent = projectModel.ProjectContent.AddAssemblyReferences(QCReferences.Value);
            }

            // For each new file, we need to integrate it into the project content
            var fileModelsInProject = projectModel.GetFileDescendants().ToArray();
            foreach (var fileModelInProject in fileModelsInProject)
            {
                IntegrateFileModel(projectModel, fileModelInProject);
            }

            // We can return now if no code completion was requested
            if (projectAnalysisRequest.CodeCompletionParameters == null)
            {
                projectAnalysisResult.TimeElapsed = sw.Elapsed;
                return projectAnalysisResult;
            }

            // Now it's time to give attention specifically to the matter of resolving the code completion
            // options.  This, of course, requires a deeper analysis of the specified file...
            
            var codeCompletionParams = projectAnalysisRequest.CodeCompletionParameters;

            // Locate the file in the project
            ProjectFileModel fileModel = projectModel.FindFile(codeCompletionParams.FileId);
            if (fileModel == null)
                throw new Exception("Specified file does not exist in this project");
            

            // Create a TypeSystem.ICompilation that allows resolving within the project.
            var compilation = projectModel.ProjectContent.CreateCompilation();

            #region Resolve text cursor/caret location
            
            // The text cursor position is crucial to creating a properly-scoped type resolution context
            // so as to get relevant code completion suggestions.
            int textCursorOffset = 0;
            TextLocation textCursorLocation = new TextLocation(1, 1);
            ReadOnlyDocument doc = new ReadOnlyDocument(fileModel.Content);
            try
            {
                // if line and column aren't set, we'll assume that the cursor offset/index is set
                if (codeCompletionParams.Line == 0 && codeCompletionParams.Column == 0)
                {
                    textCursorOffset = codeCompletionParams.Offset;
                    if (textCursorOffset < 0) textCursorOffset = 0;
                    textCursorLocation = doc.GetLocation(textCursorOffset);
                }
                // if either line or column are invalid (i.e. <= 0), then we'll use offset 0 instead
                else if (codeCompletionParams.Line <= 0 || codeCompletionParams.Column <= 0)
                {
                    textCursorOffset = 0;
                }
                else
                {
                    textCursorLocation = new TextLocation(codeCompletionParams.Line, codeCompletionParams.Column);
                    textCursorOffset = doc.GetOffset(textCursorLocation);
                    codeCompletionParams.Offset = textCursorOffset;
                }
            }
            catch (Exception)
            {
                textCursorOffset = 0;
                textCursorLocation = new TextLocation(1, 1);
            }
            finally
            {
                projectAnalysisResult.Line = textCursorLocation.Line;
                projectAnalysisResult.Column = textCursorLocation.Column;
                projectAnalysisResult.Offset = textCursorOffset;
            }

            #endregion

            #region Create and Refine the type resolution context as much as possible based upon the cursor position

            var typeResolveContext = new CSharpTypeResolveContext(compilation.MainAssembly);
            // Constrain the resolve context by using scope
            typeResolveContext = typeResolveContext
                .WithUsingScope(fileModel.UnresolvedFile.GetUsingScope(textCursorLocation)
                .Resolve(compilation));

            var curDef = fileModel.UnresolvedFile.GetInnermostTypeDefinition(textCursorLocation);
            if (curDef != null)
            {
                var resolvedDef = curDef.Resolve(typeResolveContext).GetDefinition();
                typeResolveContext = typeResolveContext.WithCurrentTypeDefinition(resolvedDef);
                var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= textCursorLocation && textCursorLocation < m.BodyRegion.End);
                if (curMember != null)
                {
                    typeResolveContext = typeResolveContext.WithCurrentMember(curMember);
                }
            }

            #endregion

            // The purpose of the rest of these steps is a little fuzzy in my mind...  
            // I'm still trying to understand them fully and if/why they're all needed.
            // It seems there is some redundancy here...

            var completionContext = new DefaultCompletionContextProvider(doc, fileModel.UnresolvedFile);

            #region Add Preprocessor Symbols??
            completionContext.AddSymbol("TEST");
            foreach (var sym in fileModel.SyntaxTree.ConditionalSymbols)
                completionContext.AddSymbol(sym);
            #endregion

            var completionDataFactory = new CodeCompletionDataFactory(new CSharpResolver(typeResolveContext));
            
            var completionEngine = new CSharpCompletionEngine(doc, completionContext, completionDataFactory, projectModel.ProjectContent, typeResolveContext);
            completionEngine.EolMarker = Environment.NewLine;
            completionEngine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
            projectModel.CompletionEngine = completionEngine;

            // Attach contextual info to analysis result
            GetDocumentContext(projectAnalysisResult, textCursorOffset, doc);

            // Finally, generate completion data!
            var completionOptions = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();

            projectAnalysisResult.CompletionOptions = completionOptions.OrderBy(x => x.CompletionText).ToArray();
            projectAnalysisResult.AutoCompleteEmptyMatch = completionEngine.AutoCompleteEmptyMatch;
            projectAnalysisResult.AutoSelect = completionEngine.AutoSelect;
            projectAnalysisResult.DefaultCompletionString = completionEngine.DefaultCompletionString;

            int startPos, wordLength;
            if (completionEngine.TryGetCompletionWord(textCursorOffset, out startPos, out wordLength))
            {
                //Debug.WriteLine("TryGetCompletionWord :: startpos:{0}  wordlength:{1}", startPos, wordLength);
                string completionWord = projectAnalysisResult.CompletionWord = doc.GetText(startPos, wordLength);

                if (!string.IsNullOrWhiteSpace(completionWord))
                {
                    var bestMatch = projectAnalysisResult.CompletionOptions
                        .FirstOrDefault(x => x.CompletionText.CompareTo(completionWord) >= 0);
                    projectAnalysisResult.BestMatchToCompletionWord = bestMatch;
                    //if (bestMatch != null)
                        //projectAnalysisResult.BestMatchToCompletionWord = bestMatch.CompletionText;
                }
            }

            projectAnalysisResult.TimeElapsed = sw.Elapsed;

            return projectAnalysisResult;
        }
		static SearchResultMatch CreateSearchResultMatch(ReferenceEntry entry)
		{
			ITextSource textSource = SD.FileService.GetFileContent(entry.fileName);
			var document = new ReadOnlyDocument(textSource, entry.fileName);
			TextLocation start = document.GetLocation(entry.minChar);
			TextLocation end = document.GetLocation(entry.minChar + entry.length);
			IHighlighter highlighter = SD.EditorControlService.CreateHighlighter(document);
			return SearchResultMatch.Create(document, start, end, highlighter);
		}
		public static CSharpCompletionEngine CreateEngine(string text, out int cursorPosition, params IUnresolvedAssembly[] references)
		{
			string parsedText;
			string editorText;
			cursorPosition = text.IndexOf('$');
			int endPos = text.IndexOf('$', cursorPosition + 1);
			if (endPos == -1) {
				if (cursorPosition < 0) {
					parsedText = editorText = text;
				} else {
					parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1);
				}
			} else {
					parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1);
					editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1);
					cursorPosition = endPos - 1; 
			}
			var doc = new ReadOnlyDocument(editorText);

			IProjectContent pctx = new CSharpProjectContent();
			var refs = new List<IUnresolvedAssembly> { mscorlib.Value, systemCore.Value, systemAssembly.Value, systemXmlLinq.Value };
			if (references != null)
				refs.AddRange (references);

			pctx = pctx.AddAssemblyReferences(refs);

			var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs");
			syntaxTree.Freeze();

			var unresolvedFile = syntaxTree.ToTypeSystem();
			pctx = pctx.AddOrUpdateFiles(unresolvedFile);

			var cmp = pctx.CreateCompilation();
			var loc = cursorPosition > 0 ? doc.GetLocation(cursorPosition) : new TextLocation (1, 1);

			var rctx = new CSharpTypeResolveContext(cmp.MainAssembly);
			rctx = rctx.WithUsingScope(unresolvedFile.GetUsingScope(loc).Resolve(cmp));

			var curDef = unresolvedFile.GetInnermostTypeDefinition(loc);
			if (curDef != null) {
					var resolvedDef = curDef.Resolve(rctx).GetDefinition();
					rctx = rctx.WithCurrentTypeDefinition(resolvedDef);
					var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= loc && loc < m.BodyRegion.End);
					if (curMember != null) {
							rctx = rctx.WithCurrentMember(curMember);
					}
			}
			var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
			mb.AddSymbol ("TEST");
			var engine = new CSharpCompletionEngine(doc, mb, new TestFactory(new CSharpResolver (rctx)), pctx, rctx);

			engine.EolMarker = Environment.NewLine;
			engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
			return engine;
		}
        // i'm not using this...
        public static CSharpCompletionEngine CreateEngine(string text, out int cursorPosition, params IUnresolvedAssembly[] references)
        {
            string parsedText;
            string editorText;
            cursorPosition = text.IndexOf('$');
            int endPos = text.IndexOf('$', cursorPosition + 1);
            if (endPos == -1)
            {
                if (cursorPosition < 0)
                {
                    parsedText = editorText = text;
                }
                else
                {
                    parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1);
                }
            }
            else
            {
                parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1);
                editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1);
                cursorPosition = endPos - 1;
            }
            var doc = new ReadOnlyDocument(editorText);

            IProjectContent projContent = new CSharpProjectContent();
            var refs = new List<IUnresolvedAssembly> { mscorlib.Value, systemCore.Value, systemAssembly.Value, systemXmlLinq.Value };
            if (references != null)
                refs.AddRange(references);

            projContent = projContent.AddAssemblyReferences(refs);

            // Parse => SyntaxTree
            var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs");
            syntaxTree.Freeze();

            var unresolvedFile = syntaxTree.ToTypeSystem();
            // Add CSharpUnresolvedFile to CSharpProjectContent
            projContent = projContent.AddOrUpdateFiles(unresolvedFile);

            // Create a TypeSystem.ICompilation that allows resolving within the project.
            var compilation = projContent.CreateCompilation();
            var textCursorLocation = cursorPosition > 0 ? doc.GetLocation(cursorPosition) : new TextLocation(1, 1);


            #region Create and Refine the type resolution context as much as possible 

            var typeResolveContext = new CSharpTypeResolveContext(compilation.MainAssembly);
            typeResolveContext = typeResolveContext.WithUsingScope(unresolvedFile.GetUsingScope(textCursorLocation).Resolve(compilation));

            var curDef = unresolvedFile.GetInnermostTypeDefinition(textCursorLocation);
            if (curDef != null)
            {
                var resolvedDef = curDef.Resolve(typeResolveContext).GetDefinition();
                typeResolveContext = typeResolveContext.WithCurrentTypeDefinition(resolvedDef);
                var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= textCursorLocation && textCursorLocation < m.BodyRegion.End);
                if (curMember != null)
                {
                    typeResolveContext = typeResolveContext.WithCurrentMember(curMember);
                }
            }

            #endregion
            
            // Cool!  Marry the concept of content & typed 
            var completionContext = new DefaultCompletionContextProvider(doc, unresolvedFile);
            #region Add Preprocessor Symbols
            completionContext.AddSymbol("TEST");
            foreach (var sym in syntaxTree.ConditionalSymbols)
            {
                completionContext.AddSymbol(sym);
            }
            #endregion
            var engine = new CSharpCompletionEngine(doc, completionContext, new TestCompletionDataFactory(new CSharpResolver(typeResolveContext)), projContent, typeResolveContext);

            engine.EolMarker = Environment.NewLine;
            engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
            return engine;
        }