コード例 #1
0
        /// <summary>
        /// Populate methods and classes dictionaries from content lines
        /// </summary>
        /// <param name="contentLines">
        /// A <see cref="System.String[]"/>: Each line of file content
        /// </param>
        /// <remarks>
        /// Maintain a stack of lines that increase the scope, 
        /// then pop as the scope is decreased.
        /// Use scope begin/end for region/fold population.
        /// </remarks>
        /// <returns>
        /// A <see cref="System.Boolean"/>: Success/failure
        /// </returns>
        bool RunStack(string[] contentLines)
        {
            Stack<KeyValuePair<int,RubyDeclaration>> stack = new Stack<KeyValuePair<int,RubyDeclaration>> ();
            int i = 1;
            Match match;

            foreach (string aline in contentLines) {
                string line = aline.Trim ();
                if (line.StartsWith ("end", StringComparison.Ordinal) &&
                    (3 == line.Length || !char.IsLetterOrDigit (line[3]))) {
                    if (0 == stack.Count){
                        // Console.WriteLine ("RubyDocumentParser: Popping empty stack at {0}", i);
                        return false;
                    }// stack imbalance

                    KeyValuePair<int,RubyDeclaration> poppedPair = stack.Pop ();
                    if (!string.IsNullOrEmpty (poppedPair.Value.name)) {
                        // Console.WriteLine ("Got {0} {1} from {2} to {3}", methods.ContainsKey(poppedPair.Key)? "method": "class", poppedPair.Value, poppedPair.Key, i);
                        if (methods.ContainsKey (poppedPair.Key)) {
                            methods[poppedPair.Key].endLine = i;
                        }// end of method definition
                        if (classes.ContainsKey (poppedPair.Key)) {
                            classes[poppedPair.Key].endLine = i;
                        }// end of class definition
                        if (modules.ContainsKey (poppedPair.Key)) {
                            modules[poppedPair.Key].endLine = i;
                        }// end of module definition
                    }// only care about method and class definitions
                }// Scope decrease

                foreach (string sb in scopeBeginners) {
                    if (line.StartsWith (sb, StringComparison.Ordinal) && !line.EndsWith ("end", StringComparison.Ordinal) &&
                        (line.Length == sb.Length || char.IsWhiteSpace (line[sb.Length]) || char.IsPunctuation (line[sb.Length]))) {
                        stack.Push (new KeyValuePair<int,RubyDeclaration> (i, new RubyDeclaration (i, aline.Length, i, string.Empty, line)));
                        break;
                    }
                }// check for unimportant scope increase

                if (null != (match = doEndBlock.Match (line)) && match.Success && !match.Groups["end"].Success) {
                    stack.Push (new KeyValuePair<int,RubyDeclaration> (i, new RubyDeclaration (i, aline.Length, i, string.Empty, line)));
                }// check for do/end-scoped block with inline do
                else if (null != (match = methodDefinition.Match (line)) && match.Success) {
                    RubyDeclaration method = methods[i] = new RubyDeclaration (i, aline.Length, i, match.Groups["name"].Value, line);
                    stack.Push (new KeyValuePair<int,RubyDeclaration> (i, method));
                }// begin method definition
                else if (null != (match = classDefinition.Match (line)) && match.Success) {
                    if (match.Groups["module"].Success && !string.IsNullOrEmpty (match.Groups["module"].Value)) {
                        modules[i] = new RubyDeclaration (i, line.Length+1, i, match.Groups["module"].Value, line);
                    }
                    RubyDeclaration klass = classes[i] = new RubyDeclaration (i, aline.Length, i, match.Groups["name"].Value, line);
                    stack.Push (new KeyValuePair<int,RubyDeclaration> (i, klass));
                }// begin class definition
                else if (null != (match = moduleDefinition.Match (line)) && match.Success) {
                    RubyDeclaration module = modules[i] = new RubyDeclaration (i, aline.Length, i, match.Groups["name"].Value, line);
                    stack.Push (new KeyValuePair<int,RubyDeclaration> (i, module));
                }// begin module definition
                ++i;
            }// parse line

            return (0 == stack.Count);
        }
コード例 #2
0
        /// <summary>
        /// Populate a module with classes
        /// </summary>
        void PopulateClasses(CompilationUnit cu, RubyDeclaration parent)
        {
            List<int> removal = new List<int> ();

            foreach (KeyValuePair<int,RubyDeclaration> mpair in classes) {
                if (mpair.Key >= parent.beginLine && mpair.Key <= parent.endLine) {
                    DomType myclass = new DomType (cu, ClassType.Class, mpair.Value.name, new DomLocation (mpair.Value.beginLine, 1),
                                                   parent.name, new DomRegion (mpair.Value.beginLine, mpair.Value.beginColumn+1,
                                                                               mpair.Value.endLine, int.MaxValue),
                                                                               new List<IMember> ());
                    PopulateMethods (myclass);
                    cu.Add (myclass);
                    removal.Add (mpair.Key);
                }// Add classes that are declared within the parent's scope
            }// Check detected classes

            // Remove used classes from map
            foreach (int key in removal){ classes.Remove (key); }
        }