private void TestParser(string source, StatementListBuilder <StatementType, ParserTokenType> expected)
        {
            StringTextProvider textProvider = new StringTextProvider(source);
            var actual = RtypeStatementParser.ParseStatements(new Position(0, 0, 0), textProvider);

            Assert.True(expected.SequenceEqual(actual, this.statementComparer));
        }
Пример #2
0
        /// <summary>
        /// Scans the given SnapshotSpan for potential matches for this classification.
        /// </summary>
        /// <param name="span">The span currently being classified</param>
        /// <returns>A list of ClassificationSpans that represent spans identified to be of this classification</returns>
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            List <ClassificationSpan> classifications = new List <ClassificationSpan>();

            try
            {
                using (ReaderTextProvider textProvider = new ReaderTextProvider(new TextSnapshotToTextReader(span.Snapshot)))
                {
                    // We parse the whole buffer for statements, not just the current line,
                    // because we need to know if we're on a continuation line.
                    // TODO: Cache the "beginning of logical line" points so that we
                    // don't have to re-parse everything each time?
                    IEnumerable <Statement <StatementType, ParserTokenType> > statements = null;

                    switch (this.language)
                    {
                    case ParserLanguage.Rtype:
                        statements = RtypeStatementParser.ParseStatements(new Position(0, 0, 0), textProvider);
                        break;

                    case ParserLanguage.Xml:
                        statements = XmlStatementParser.ParseStatements(new Position(0, 0, 0), textProvider);
                        break;
                    }

                    int spanStart = span.Start.Position;
                    int spanEnd   = span.End.Position;

                    foreach (var statement in statements)
                    {
                        if (statement.Range.End.Offset <= spanStart)
                        {
                            continue;
                        }

                        if (statement.Range.Start.Offset >= spanEnd)
                        {
                            break;
                        }

                        // for a comment statement, we don't have to look at the
                        // individual tokens...
                        if (statement.StatementType == StatementType.Comment)
                        {
                            var classification = this.commentType;

                            // Ensure the returned span doesn't extend past the request!
                            var classifiedSpan = span.Intersection(span.Snapshot.CreateSpanFromSwix(statement.Range));

                            if (classifiedSpan.HasValue)
                            {
                                classifications.Add(new ClassificationSpan(classifiedSpan.Value, classification));
                            }
                        }
                        else
                        {
                            foreach (var token in statement.AllTokens)
                            {
                                if (token.Range.End.Offset <= span.Start.Position)
                                {
                                    continue;
                                }

                                if (token.Range.Start.Offset >= span.End.Position)
                                {
                                    break;
                                }

                                IClassificationType classification = null;

                                switch (token.TokenType)
                                {
                                case ParserTokenType.Unknown:
                                    classification = this.delimiterType;
                                    break;

                                case ParserTokenType.Whitespace:
                                    classification = this.whitespaceType;
                                    break;

                                case ParserTokenType.Comment:
                                    classification = this.commentType;
                                    break;

                                case ParserTokenType.UseKeyword:
                                    classification = this.keywordType;
                                    break;

                                case ParserTokenType.Object:
                                    classification = this.objectType;
                                    break;

                                case ParserTokenType.PropertyName:
                                    classification = this.propertyType;
                                    break;

                                case ParserTokenType.Equals:
                                    classification = this.assignmentType;
                                    break;

                                case ParserTokenType.PropertyValue:
                                case ParserTokenType.DoubleQuote:
                                case ParserTokenType.SingleQuote:
                                    classification = this.valueType;
                                    break;

                                case ParserTokenType.NamespacePrefix:
                                    classification = this.namespacePrefixType;
                                    break;

                                case ParserTokenType.NamespacePrefixDeclaration:
                                    // TODO
                                    break;

                                case ParserTokenType.NamespaceDeclaration:
                                    // TODO
                                    break;

                                case ParserTokenType.AttachedPropertyObject:
                                    classification = this.attachableObjectType;
                                    break;

                                case ParserTokenType.LeftAngle:
                                case ParserTokenType.RightAngle:
                                case ParserTokenType.Colon:
                                case ParserTokenType.Slash:
                                case ParserTokenType.Period:
                                    classification = this.delimiterType;
                                    break;

                                default:
                                    break;
                                }

                                if (classification != null)
                                {
                                    // Ensure the returned span doesn't extend past the request!
                                    var classifiedSpan = span.Intersection(span.Snapshot.CreateSpanFromSwix(token.Range));

                                    if (classifiedSpan.HasValue)
                                    {
                                        classifications.Add(new ClassificationSpan(classifiedSpan.Value, classification));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
            }

            return(classifications);
        }