public static StatelessProjectResponse Server_HandleStatelessCodeCompletionRequest(StatelessProjectRequest request)
        {
            // Convert web request model to internal analysis model
            ProjectAnalysisRequest analysisRequest = new ProjectAnalysisRequest();
            analysisRequest.ProjectModel = ProjectModelConverters.FromDtoToModel(request.Project);
            if (request.CodeCompletionParameters != null)
            {
                analysisRequest.CodeCompletionParameters = new ProjectAnalysisCodeCompletionParameters()
                {
                    CtrlSpace = request.CodeCompletionParameters.CtrlSpace,
                    Offset = request.CodeCompletionParameters.Offset,
                    FileId = request.CodeCompletionParameters.FileId,
                    Line = request.CodeCompletionParameters.Line,
                    Column = request.CodeCompletionParameters.Column
                };
            }

            // Analyze!
            ProjectAnalysisResult analysisResult = NRefactoryUtils.RunFullProjectAnalysis(analysisRequest);

            // Convert analysis result model to web service model
            StatelessProjectResponse response = new StatelessProjectResponse();
            if (analysisResult.CompletionOptions != null)
            {
                response.CompletionOptions = analysisResult.CompletionOptions
                    .Select(CodeCompletionResultUtility.FromICompletionDataToFileCodeCompletionResult)
                    .ToArray();
                for (int i = 0, len = response.CompletionOptions.Length; i < len; i++)
                    response.CompletionOptions[i].Id = i;
                response.CompletionWord = analysisResult.CompletionWord;
                if (analysisResult.BestMatchToCompletionWord != null)
                    response.BestMatchToCompletionWord = response.CompletionOptions.FirstOrDefault(x => x.CompletionText == analysisResult.BestMatchToCompletionWord.CompletionText);
            }
            var allErrors = new List<FileParseResult>();
            foreach (var fileModel in analysisRequest.ProjectModel.GetFileDescendants())
            {
                allErrors.AddRange(fileModel.Parser.ErrorsAndWarnings
                                       .Select(x => new FileParseResult()
                                       {
                                           FileId = fileModel.Id,
                                           FileName = fileModel.Name,
                                           Line = x.Region.BeginLine,
                                           Column = x.Region.BeginColumn,
                                           Type = x.ErrorType,
                                           Message = x.Message
                                       }).ToArray());
            }
            response.Errors = allErrors.ToArray();
            response.MsElapsed = analysisResult.TimeElapsed.TotalMilliseconds; // string.Format("{0}", analysisResult.TimeElapsed.TotalMilliseconds);

            return response;
        }
        private void AnalyzeProject(bool ctrlSpace)
        {
            ctrlSpace = true;
            var sw = Stopwatch.StartNew();

            var projectVm = (ProjectViewModel)DataContext;
            var fileVm = projectVm.SelectedProjectItem as ProjectFileViewModel;
            if (fileVm == null)
            {
                Logger.AppendLine("A file must be selected");
                return;
            }
            fileVm.CaretIndex = SelectedFileContent.CaretIndex;

            // Synchronize the view's content with the viewmodel (since by default this is only done AFTER the textbox loses focus)
            fileVm.Content = SelectedFileContent.Text;

            var projectDto = ProjectMVVMConverters.FromViewModelToModel(projectVm);
            var request = new StatelessProjectRequest()
            {
                Project = projectDto,
                CodeCompletionParameters = new StatelessProjectCodeCompletionParameters()
                {
                    CtrlSpace = ctrlSpace,
                    FileId = fileVm.Id,
                    Offset = fileVm.CaretIndex
                }
            };

            StatelessProjectResponse response = MockWebServiceUtility.Server_HandleStatelessCodeCompletionRequest(request);

            var jsonResponse = JsonConvert.SerializeObject(response, Formatting.Indented);
            //Logger.AppendLine(jsonResponse);

            // Summarize results...
            Logger.AppendLine("Project analysis completed in {0} ms", sw.ElapsedMilliseconds);

            if (response.CompletionOptions != null)
            {
                // Order results by completion text
                response.CompletionOptions = response.CompletionOptions.OrderBy(x => x.CompletionText).ToArray();
                Logger.AppendLine("{0} code completion option(s) generated.", response.CompletionOptions.Length);

                // Try to find closest matching completion result
                if (string.IsNullOrWhiteSpace(response.CompletionWord))
                {
                    Logger.AppendLine("No code completion word detected.");
                }
                else
                {
                    //response. .CompletionOptionMostCloselyMatchingCompletionWord = response.CompletionOptions
                    //    .FirstOrDefault(x => x.CompletionText.CompareTo(response.CompletionWord) >= 0);
                    //response.CompletionOptionMostCloselyMatchingCompletionWord = response.CompletionOptions.FirstOrDefault(x => x.CompletionText.StartsWith(response.CompletionWord, StringComparison.InvariantCultureIgnoreCase));
                    if (response.BestMatchToCompletionWord != null)
                    {
                        Logger.AppendLine("Detected code completion word, \"{0}\", most closely matches completion option \"{1}\".",
                                          response.CompletionWord, response.BestMatchToCompletionWord.CompletionText);
                    }
                    else
                    {
                        Logger.AppendLine("Detected code completion word: {0}", response.CompletionWord);
                    }
                }

            }

            Logger.SetCodeCompletionOptions(response.CompletionOptions, response.BestMatchToCompletionWord); // response.CompletionWord);

            if (response.Errors != null)
            {
                Logger.AppendLine("{0} error(s) detected.", response.Errors.Length);
                if (response.Errors.Length > 0)
                    foreach (var err in response.Errors)
                        Logger.AppendLine("{0}: In file {1} ({2}, {3}): {4}", err.Type, err.FileName, err.Line, err.Column, err.Message);
            }

        }