public NRefactoryResolver(IProjectContent projectContent, LanguageProperties languageProperties)
 {
     if (projectContent == null)
     {
         throw new ArgumentNullException("projectContent");
     }
     if (languageProperties == null)
     {
         throw new ArgumentNullException("languageProperties");
     }
     this.languageProperties = languageProperties;
     this.projectContent     = projectContent;
     if (languageProperties is LanguageProperties.CSharpProperties)
     {
         language = NR.SupportedLanguage.CSharp;
     }
     else if (languageProperties is LanguageProperties.VBNetProperties)
     {
         language = NR.SupportedLanguage.VBNet;
     }
     else
     {
         throw new NotSupportedException("The language " + languageProperties.ToString() + " is not supported in the resolver");
     }
 }
 private NRefactoryRefactoringProvider(NR.SupportedLanguage language)
 {
     this.language = language;
 }
        /// <summary>
        /// Creates a new class containing only the specified member.
        /// This is useful because we only want to parse current method for local variables,
        /// as all fields etc. are already prepared in the AST.
        /// </summary>
        public static TextReader ExtractMethod(string fileContent, IMember member,
                                               NR.SupportedLanguage language, int caretLine)
        {
            // As the parse information is always some seconds old, the end line could be wrong
            // if the user just inserted a line in the method.
            // We can ignore that case because it is sufficient for the parser when the first part of the
            // method body is ok.
            // Since we are operating directly on the edited buffer, the parser might not be
            // able to resolve invalid declarations.
            // We can ignore even that because the 'invalid line' is the line the user is currently
            // editing, and the declarations he is using are always above that line.


            // The ExtractMethod-approach has the advantage that the method contents do not have
            // do be parsed and stored in memory before they are needed.
            // Previous SharpDevelop versions always stored the SharpRefactory[VB] parse tree as 'Tag'
            // to the AST CompilationUnit.
            // This approach doesn't need that, so one could even go and implement a special parser
            // mode that does not parse the method bodies for the normal run (in the ParserUpdateThread or
            // SolutionLoadThread). That could improve the parser's speed dramatically.

            if (member.Region.IsEmpty)
            {
                return(null);
            }
            int startLine = member.Region.BeginLine;

            if (startLine < 1)
            {
                return(null);
            }
            DomRegion bodyRegion;

            if (member is IMethodOrProperty)
            {
                bodyRegion = ((IMethodOrProperty)member).BodyRegion;
            }
            else if (member is IEvent)
            {
                bodyRegion = ((IEvent)member).BodyRegion;
            }
            else
            {
                return(null);
            }
            if (bodyRegion.IsEmpty)
            {
                return(null);
            }
            int endLine = bodyRegion.EndLine;

            // Fix for SD2-511 (Code completion in inserted line)
            if (language == NR.SupportedLanguage.CSharp)
            {
                // Do not do this for VB: the parser does not correct create the
                // ForEachStatement when the method in truncated in the middle
                // VB does not have the "inserted line looks like variable declaration"-problem
                // anyways.
                if (caretLine > startLine && caretLine < endLine)
                {
                    endLine = caretLine;
                }
            }

            int offset = 0;

            for (int i = 0; i < startLine - 1; ++i)               // -1 because the startLine must be included
            {
                offset = fileContent.IndexOf('\n', offset) + 1;
                if (offset <= 0)
                {
                    return(null);
                }
            }
            int startOffset = offset;

            for (int i = startLine - 1; i < endLine; ++i)
            {
                int newOffset = fileContent.IndexOf('\n', offset) + 1;
                if (newOffset <= 0)
                {
                    break;
                }
                offset = newOffset;
            }
            int    length = offset - startOffset;
            string classDecl, endClassDecl;

            if (language == NR.SupportedLanguage.VBNet)
            {
                classDecl    = "Class A";
                endClassDecl = "End Class\n";
            }
            else
            {
                classDecl    = "class A {";
                endClassDecl = "}\n";
            }
            System.Text.StringBuilder b = new System.Text.StringBuilder(classDecl, length + classDecl.Length + endClassDecl.Length + startLine - 1);
            b.Append('\n', startLine - 1);
            b.Append(fileContent, startOffset, length);
            b.Append(endClassDecl);
            return(new System.IO.StringReader(b.ToString()));
        }