public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            RuleBlock rule = (RuleBlock)item;

            if (!rule.IsValid || context == null)
                return ItemCheckResult.Continue;

            IEnumerable<string> properties = from d in rule.Declarations
                                             where d.PropertyName != null && d.Values.Count < 2
                                             select d.PropertyName.Text;


            foreach (string shorthand in _cache.Keys)
            {
                if (_cache[shorthand].All(p => properties.Contains(p)))
                {
                    Declaration dec = rule.Declarations.First(p => p.PropertyName != null && _cache[shorthand].Contains(p.PropertyName.Text));
                    string message = string.Format(CultureInfo.CurrentCulture, Resources.PerformanceUseShorthand, string.Join(", ", _cache[shorthand]), shorthand);

                    context.AddError(new SimpleErrorTag(dec, message));
                }
            }

            return ItemCheckResult.Continue;
        }
 public SimpleErrorTag(ParseItem item, string errorMessage, int length)
 {
     _item = item;
     _errorMessage = errorMessage;
     _length = length;
     Flags = GetLocation();
 }
 public SimpleErrorTag(ParseItem item, string errorMessage, CssErrorFlags flags = CssErrorFlags.TaskListMessage | CssErrorFlags.UnderlinePurple)
 {
     _item = item;
     _errorMessage = errorMessage;
     _length = AfterEnd - Start;
     Flags = flags;
 }
        private bool SchemaLookup(ParseItem item)
        {
            if (item is ClassSelector || item is IdSelector || item is ItemName || item.Parent is RuleBlock || item.Parent is StyleSheet)
                return false;

            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaRootForBuffer(TextView.TextBuffer);

            Declaration dec = item.FindType<Declaration>();
            if (dec != null && dec.PropertyName != null)
                return OpenReferenceUrl(schema.GetProperty, dec.PropertyName.Text, "http://realworldvalidator.com/css/properties/");

            PseudoClassFunctionSelector pseudoClassFunction = item.FindType<PseudoClassFunctionSelector>();
            if (pseudoClassFunction != null)
                return OpenReferenceUrl(schema.GetPseudo, pseudoClassFunction.Colon.Text + pseudoClassFunction.Function.FunctionName.Text + ")", "http://realworldvalidator.com/css/pseudoclasses/");

            PseudoElementFunctionSelector pseudoElementFunction = item.FindType<PseudoElementFunctionSelector>();
            if (pseudoElementFunction != null)
                return OpenReferenceUrl(schema.GetPseudo, pseudoElementFunction.DoubleColon.Text + pseudoElementFunction.Function.FunctionName.Text + ")", "http://realworldvalidator.com/css/pseudoelements/");

            PseudoElementSelector pseudoElement = item.FindType<PseudoElementSelector>();
            if (pseudoElement != null && pseudoElement.PseudoElement != null)
                return OpenReferenceUrl(schema.GetPseudo, pseudoElement.DoubleColon.Text + pseudoElement.PseudoElement.Text, "http://realworldvalidator.com/css/pseudoelements/");

            PseudoClassSelector pseudoClass = item.FindType<PseudoClassSelector>();
            if (pseudoClass != null && pseudoClass.PseudoClass != null)
                return OpenReferenceUrl(schema.GetPseudo, pseudoClass.Colon.Text + pseudoClass.PseudoClass.Text, "http://realworldvalidator.com/css/pseudoclasses/");

            AtDirective directive = item.FindType<AtDirective>();
            if (directive != null)
                return OpenReferenceUrl(schema.GetAtDirective, directive.At.Text + directive.Keyword.Text, "http://realworldvalidator.com/css/atdirectives/");

            return false;
        }
 public SimpleErrorTag(ParseItem item, string errorMessage)
 {
     _item = item;
     _errorMessage = errorMessage;
     _length = AfterEnd - Start;
     Flags = GetLocation();
 }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (!WESettings.GetBoolean(WESettings.Keys.ValidateZeroUnit))
                return ItemCheckResult.Continue;

            NumericalValue number = (NumericalValue)item;
            UnitValue unit = number as UnitValue;

            if (unit == null || context == null)
                return ItemCheckResult.Continue;

            // The 2nd and 3rd arguments to hsl() require units even when zero
            var function = unit.Parent.Parent as FunctionColor;
            if (function != null && function.FunctionName.Text.StartsWith("hsl", StringComparison.OrdinalIgnoreCase)) {
                var arg = unit.Parent as FunctionArgument;
                if (arg != function.Arguments[0])
                    return ItemCheckResult.Continue;
            }

            if (number.Number.Text == "0" && unit.UnitType != UnitType.Unknown && unit.UnitType != UnitType.Time)
            {
                string message = string.Format(Resources.BestPracticeZeroUnit, unit.UnitToken.Text);
                context.AddError(new SimpleErrorTag(number, message));
            }

            return ItemCheckResult.Continue;
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            FunctionColor function = (FunctionColor)item;

            if (!function.IsValid)
                yield break;

            ColorModel model = ColorParser.TryParseColor(function.Text, ColorParser.Options.AllowAlpha);
            if (model != null)
            {
                // Don't convert RGBA and HSLA to HEX or named color
                if (model.Alpha == 1)
                {
                    if (ColorConverterSmartTagAction.GetNamedColor(model.Color) != null)
                    {
                        yield return new ColorConverterSmartTagAction(itemTrackingSpan, model, ColorFormat.Name);
                    }

                    yield return new ColorConverterSmartTagAction(itemTrackingSpan, model, ColorFormat.RgbHex3);
                }

                if (model.Format == ColorFormat.Rgb)
                {
                    yield return new ColorConverterSmartTagAction(itemTrackingSpan, model, ColorFormat.Hsl);
                }
                else if (model.Format == ColorFormat.Hsl)
                {
                    yield return new ColorConverterSmartTagAction(itemTrackingSpan, model, ColorFormat.Rgb);
                }
            }
        }
        public CssCompletionContext GetCompletionContext(ParseItem item, int position)
        {
            if (item.FindType<AttributeSelector>() != null)
                return null;

            return new CssCompletionContext((CssCompletionContextType)601, item.Start, item.Length, null);
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (!WESettings.Instance.Css.ValidateVendorSpecifics)
                return ItemCheckResult.Continue;

            if (!item.IsValid || context == null)
                return ItemCheckResult.Continue;

            ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null);
            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, item);

            string normalized = item.Text.Trim(':');
            ICssCompletionListEntry pseudo = schema.GetPseudo(item.Text);

            if (normalized.Length > 0 && normalized[0] == '-' && pseudo == null)
            {
                string message = string.Format(CultureInfo.CurrentCulture, Resources.ValidationVendorPseudo, item.Text);
                context.AddError(new SimpleErrorTag(item, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
                return ItemCheckResult.CancelCurrentItem;
            }
            else if (pseudo != null)
            {
                string obsolete = pseudo.GetAttribute("obsolete");
                if (!string.IsNullOrEmpty(obsolete))
                {
                    string message = string.Format(CultureInfo.CurrentCulture, Resources.BestPracticeRemoveObsolete, normalized, obsolete);
                    context.AddError(new SimpleErrorTag(item, message, CssErrorFlags.TaskListMessage));
                    return ItemCheckResult.CancelCurrentItem;
                }
            }

            return ItemCheckResult.Continue;
        }
 public SimpleErrorTag(ParseItem item, string errorMessage, int length, CssErrorFlags flags)
 {
     Item = item;
     Text = errorMessage;
     Length = length;
     Flags = flags;
 }
        private static void HandleDeclaration(ParseItem item, ICssCheckerContext context)
        {
            Declaration dec = (Declaration)item;

            if (dec == null || dec.PropertyName == null)
                return;

            if (dec.IsVendorSpecific())
            {
                string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C property", dec.PropertyName.Text);
                context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
            }

            foreach (var value in dec.Values)
            {
                string text = value.Text;
                if (!(value is NumericalValue) && text.StartsWith("-", StringComparison.Ordinal))
                {
                    int index = text.IndexOf('(');

                    if (index > -1)
                    {
                        text = text.Substring(0, index);
                    }

                    string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C value", text);
                    context.AddError(new SimpleErrorTag(value, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
                }
            }
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (item.Text.TrimStart(':').StartsWith("-"))
                return ItemCheckResult.Continue;

            ParseItem next = item.NextSibling;
            //ParseItem prev = item.PreviousSibling;
            SimpleSelector sel = item.FindType<SimpleSelector>();

            //if (item.Text == ":hover" && prev != null && _invalids.Contains(prev.Text))
            //{
            //    string error = string.Format(Resources.ValidationHoverOrder, prev.Text);
            //    context.AddError(new SimpleErrorTag(item, error, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed));
            //}

            if (next != null)
            {
                if (next.Text.StartsWith(":") && item.IsPseudoElement() && !next.IsPseudoElement())
                {
                    string error = string.Format(Resources.ValidationPseudoOrder, item.Text, next.Text);
                    context.AddError(new SimpleErrorTag(item, error, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed));
                }

                else if (!next.Text.StartsWith(":") && item.AfterEnd == next.Start)
                {
                    string error = string.Format(Resources.BestPracticePseudosAfterOtherSelectors, next.Text);
                    context.AddError(new SimpleErrorTag(next, error));
                }
            }

            return ItemCheckResult.Continue;
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (!WESettings.Instance.Css.ValidateVendorSpecifics)
                return ItemCheckResult.Continue;

            Declaration dec = (Declaration)item;

            if (!dec.IsValid || !dec.IsVendorSpecific() || context == null)
                return ItemCheckResult.Continue;

            ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null);
            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, item);

            ICssCompletionListEntry prop = schema.GetProperty(dec.PropertyName.Text);

            if (prop == null)
            {
                string message = string.Format(CultureInfo.CurrentCulture, Resources.ValidationVendorDeclarations, dec.PropertyName.Text);
                context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
                return ItemCheckResult.CancelCurrentItem;
            }
            else
            {
                string obsolete = prop.GetAttribute("obsolete");
                if (!string.IsNullOrEmpty(obsolete))
                {
                    string message = string.Format(CultureInfo.CurrentCulture, Resources.BestPracticeRemoveObsolete, dec.PropertyName.Text, obsolete);
                    context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListMessage));
                    return ItemCheckResult.CancelCurrentItem;
                }
            }

            return ItemCheckResult.Continue;
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (!WESettings.Instance.Css.ValidateVendorSpecifics)
                return ItemCheckResult.Continue;

            AtDirective directive = (AtDirective)item;

            if (context == null || !directive.IsValid || !directive.IsVendorSpecific())
                return ItemCheckResult.Continue;

            ICssCompletionListEntry entry = VendorHelpers.GetMatchingStandardEntry(directive, context);

            if (entry != null)
            {
                var visitor = new CssItemCollector<AtDirective>();
                directive.Parent.Accept(visitor);

                if (!visitor.Items.Any(a => a != null && a.Keyword != null && "@" + a.Keyword.Text == entry.DisplayText))
                {
                    string message = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeAddMissingStandardDirective, entry.DisplayText);
                    context.AddError(new SimpleErrorTag(directive.Keyword, message));
                    return ItemCheckResult.CancelCurrentItem;
                }
            }

            return ItemCheckResult.Continue;
        }
        //private HashSet<string> _deprecated = new HashSet<string>()
        //{
        //    "-moz-opacity",
        //    "-moz-outline",
        //    "-moz-outline-style",
        //};
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            if (!WESettings.GetBoolean(WESettings.Keys.ValidateVendorSpecifics))
                return ItemCheckResult.Continue;

            Declaration dec = (Declaration)item;

            if (!dec.IsValid || !dec.IsVendorSpecific() || context == null)
                return ItemCheckResult.Continue;

            ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null);
            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, item);

            //if (_deprecated.Contains(dec.PropertyName.Text))
            //{
            //    string message = string.Format(Resources.ValidationDeprecatedVendorDeclaration, dec.PropertyName.Text);
            //    context.AddError(new SimpleErrorTag(dec.PropertyName, message));
            //    return ItemCheckResult.CancelCurrentItem;
            //}
             if (schema.GetProperty(dec.PropertyName.Text) == null)
            {
                string message = string.Format(Resources.ValidationVendorDeclarations, dec.PropertyName.Text);
                context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
                return ItemCheckResult.CancelCurrentItem;
            }

            return ItemCheckResult.Continue;
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            HexColorValue hex = (HexColorValue)item;

            if (!item.IsValid)
                yield break;

            ColorModel model = ColorParser.TryParseColor(hex.Text, ColorParser.Options.None);
            if (model != null)
            {
                if (ColorConverterSmartTagAction.GetNamedColor(model.Color) != null)
                {
                    yield return new ColorConverterSmartTagAction(itemTrackingSpan, hex, model, ColorFormat.Name);
                }

                if (model.Format == ColorFormat.RgbHex6)
                {
                    string hex3 = ColorFormatter.FormatColor(model, ColorFormat.RgbHex3);

                    if (hex3.Length == 4)
                    {
                        yield return new ColorConverterSmartTagAction(itemTrackingSpan, hex, model, ColorFormat.RgbHex3);
                    }
                }

                yield return new ColorConverterSmartTagAction(itemTrackingSpan, hex, model, ColorFormat.Rgb);
                yield return new ColorConverterSmartTagAction(itemTrackingSpan, hex, model, ColorFormat.Hsl);
            }
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            UrlItem url = (UrlItem)item;

            if (!WESettings.GetBoolean(WESettings.Keys.ValidateEmbedImages) || !url.IsValid || url.UrlString.Text.Contains("base64,") || context == null)
                return ItemCheckResult.Continue;

            string fileName = ImageQuickInfo.GetFullUrl(url.UrlString.Text, EditorExtensionsPackage.DTE.ActiveDocument.FullName);
            if (string.IsNullOrEmpty(fileName) || fileName.Contains("://"))
                return ItemCheckResult.Continue;

            FileInfo file = new FileInfo(fileName);

            if (file.Exists && file.Length < (1024 * 3))
            {
                Declaration dec = url.FindType<Declaration>();
                if (dec != null && dec.PropertyName != null && dec.PropertyName.Text[0] != '*' && dec.PropertyName.Text[0] != '_')
                {
                    string error = string.Format(Resources.PerformanceEmbedImageAsDataUri, file.Length);
                    context.AddError(new SimpleErrorTag(url.UrlString, error));
                }
            }

            return ItemCheckResult.Continue;
        }
        public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context)
        {
            UrlItem url = (UrlItem)item;

            if (!WESettings.Instance.Css.ValidateEmbedImages || !url.IsValid || url.UrlString == null || url.UrlString.Text.Contains("base64,") || context == null)
                return ItemCheckResult.Continue;

            string fileName = ImageQuickInfo.GetFullUrl(url.UrlString.Text, WebEssentialsPackage.DTE.ActiveDocument.FullName);
            if (string.IsNullOrEmpty(fileName) || fileName.Contains("://"))
                return ItemCheckResult.Continue;

            // Remove parameters if any; c:/temp/myfile.ext?#iefix
            fileName = fileName.Split('?', '#')[0];

            try
            {
                FileInfo file = new FileInfo(fileName);

                if (file.Exists && file.Length < (1024 * 3))
                {
                    Declaration dec = url.FindType<Declaration>();
                    if (dec != null && dec.PropertyName != null && dec.PropertyName.Text[0] != '*' && dec.PropertyName.Text[0] != '_')
                    {
                        string error = string.Format(CultureInfo.CurrentCulture, Resources.PerformanceEmbedImageAsDataUri, file.Length);
                        context.AddError(new SimpleErrorTag(url.UrlString, error));
                    }
                }
            }
            catch { /* Ignore any error here */ }

            return ItemCheckResult.Continue;
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            Declaration dec = (Declaration)item;

            if (!item.IsValid || position > dec.Colon.Start)
                yield break;

            RuleBlock rule = dec.FindType<RuleBlock>();
            if (!rule.IsValid)
                yield break;

            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaRootForBuffer(itemTrackingSpan.TextBuffer);

            if (!dec.IsVendorSpecific())
            {
                IEnumerable<Declaration> vendors = VendorHelpers.GetMatchingVendorEntriesInRule(dec, rule, schema);
                if (vendors.Any(v => v.Start > dec.Start))
                {
                    yield return new VendorOrderSmartTagAction(itemTrackingSpan, vendors.Last(), dec);
                }
            }
            else
            {
                ICssCompletionListEntry entry = VendorHelpers.GetMatchingStandardEntry(dec, schema);
                if (entry != null && !rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == entry.DisplayText))
                {
                    yield return new MissingStandardSmartTagAction(itemTrackingSpan, dec, entry.DisplayText);
                }
            }
        }
        protected override bool ParseSelectorToken(IItemFactory itemFactory, ITextProvider text, ITokenStream stream)
        {
            if (stream.Current.Type == TokenType.OpenBrace)
            {
                OpenBrace = Children.AddCurrentAndAdvance(stream, SassClassifierType.SquareBrace);
                if (stream.Current.Type == TokenType.Identifier)
                    Attribute = Children.AddCurrentAndAdvance(stream);

                if (IsAttributeOperator(stream.Current.Type))
                    Operator = Children.AddCurrentAndAdvance(stream);

                if (stream.Current.Type == TokenType.String || stream.Current.Type == TokenType.BadString)
                {
                    Value = itemFactory.CreateSpecificParsed<StringValue>(this, text, stream);
                    if (Value != null)
                        Children.Add(Value);
                } else if (stream.Current.Type == TokenType.Identifier)
                {
                    Value = Children.AddCurrentAndAdvance(stream, SassClassifierType.String);
                }

                if (stream.Current.Type == TokenType.CloseBrace)
                    CloseBrace = Children.AddCurrentAndAdvance(stream, SassClassifierType.SquareBrace);
            }

            return Children.Count > 0;
        }
		public CssCompletionContext GetCompletionContext(ParseItem item, int position)
		{
			Function func = (Function)item;
			if (func.FunctionName == null && func.FunctionName.Text != "var-")
				return null;

			return new CssCompletionContext((CssCompletionContextType)609, func.Arguments.TextStart, func.Arguments.TextLength, null);
		}
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            RuleSet rule = item.FindType<RuleSet>();
            if (rule == null || !rule.Block.IsValid || UsageRegistry.IsRuleUsed(rule))
                yield break;

            yield return new RemoveCssRuleSmartTagAction(itemTrackingSpan, rule);
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            RuleSet rule = item.FindType<RuleSet>();
            if (rule == null || !rule.IsValid || !rule.Block.IsValid)
                yield break;

            yield return new SortSmartTagAction(rule, itemTrackingSpan, view);
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            LessRuleBlock rule = item.FindType<LessRuleBlock>();

            if (!item.IsValid || rule == null)
                yield break;

            yield return new LessExtractVariableSmartTagAction(itemTrackingSpan, item, "@");
        }
        private static void HandlePseudo(ParseItem item, ICssCheckerContext context)
        {
            string text = item.Text.TrimStart(':');

            if (text.StartsWith("-", StringComparison.Ordinal))
            {
                string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C pseudo class/element", item.Text);
                context.AddError(new SimpleErrorTag(item, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed));
            }
        }
        public LessExtractVariableSmartTagAction(ITrackingSpan span, ParseItem item)
        {
            _span = span;
            _item = item;

            if (Icon == null)
            {
                Icon = BitmapFrame.Create(new Uri("pack://application:,,,/WebEssentials2012;component/Resources/extract.png", UriKind.RelativeOrAbsolute));
            }
        }
        public CssCompletionContext GetCompletionContext(ParseItem item, int position)
        {
            var token = item.StyleSheet.ItemBeforePosition(position);

            // Don't handle expressions. MediaFeatureContextProvider.cs does that
            if (token.FindType<MediaExpression>() != null)
                return null;

            return new CssCompletionContext((CssCompletionContextType)612, token.Start, token.Length, null);
        }
        private void UpdateCache(ParseItem item)
        {
            var visitor = new CssItemCollector<Declaration>(true);
            item.Accept(visitor);

            foreach (TokenItem token in visitor.Items.Where(d => d.Important != null).Select(d => d.Important))
            {
                if (!_cache.Contains(token))
                    _cache.Add(token);
            }
        }
        public CssCompletionContext GetCompletionContext(ParseItem item, int position)
        {
            RuleSet rule = item.FindType<RuleSet>();

            if (rule != null && rule.Parent is LessRuleBlock)
            {
                return new CssCompletionContext(CssCompletionContextType.Invalid, item.Start, item.Length, item);
            }

            return null;
        }
        public IEnumerable<ISmartTagAction> GetSmartTagActions(ParseItem item, int position, ITrackingSpan itemTrackingSpan, ITextView view)
        {
            UrlItem url = (UrlItem)item;
            if (!url.IsValid || url.UrlString == null)
                yield break;

            if (url.UrlString.Text.Contains(";base64,"))
            {
                yield return new ReverseEmbedSmartTagAction(itemTrackingSpan, url);
            }
        }
Exemple #31
0
 public CssGoToLineTag(ParseItem selector, string file)
 {
     _selector = selector;
     _file     = file;
 }
 public CssCompletionContext GetCompletionContext(ParseItem item, int position)
 {
     return(new CssCompletionContext((CssCompletionContextType)602, item.Start, item.Length, null));
 }
        // A very ugly hack for a very ugly bug: https://github.com/hcatlin/libsass/issues/324
        // Remove this and its caller in previous method, when it is fixed in original repo
        // and https://github.com/andrew/node-sass/ is released with the fix.
        // Overwriting all positions belonging to original/source file.
        private async Task <IEnumerable <CssSourceMapNode> > CorrectionsForScss(string cssFileContents)
        {
            // Sort collection for generated file.
            var sortedForGenerated = MapNodes.OrderBy(x => x.GeneratedLine)
                                     .ThenBy(x => x.GeneratedColumn)
                                     .ToList();

            ParseItem      item = null;
            Selector       selector = null;
            SimpleSelector simple = null;
            StyleSheet     styleSheet = null, cssStyleSheet = null;
            int            start = 0, indexInCollection, targetDepth;
            string         fileContents = null, simpleText = "";
            var            result            = new List <CssSourceMapNode>();
            var            contentCollection = new HashSet <string>(); // So we don't have to read file for each map item.
            var            parser            = new CssParser();

            cssStyleSheet = parser.Parse(cssFileContents, false);

            foreach (var node in MapNodes)
            {
                // Cache source file contents.
                if (!contentCollection.Contains(node.SourceFilePath))
                {
                    if (!File.Exists(node.SourceFilePath)) // Lets say someone deleted the reference file.
                    {
                        continue;
                    }

                    fileContents = await FileHelpers.ReadAllTextRetry(node.SourceFilePath);

                    contentCollection.Add(node.SourceFilePath);

                    styleSheet = _parser.Parse(fileContents, false);
                }

                start  = cssFileContents.NthIndexOfCharInString('\n', node.GeneratedLine);
                start += node.GeneratedColumn;

                item = cssStyleSheet.ItemAfterPosition(start);

                if (item == null)
                {
                    continue;
                }

                selector = item.FindType <Selector>();
                simple   = item.FindType <SimpleSelector>();

                if (selector == null || simple == null)
                {
                    continue;
                }

                simpleText = simple.Text;

                indexInCollection = sortedForGenerated.FindIndex(e => e.Equals(node));//sortedForGenerated.IndexOf(node);

                targetDepth = 0;

                for (int i = indexInCollection;
                     i >= 0 && node.GeneratedLine == sortedForGenerated[i].GeneratedLine;
                     targetDepth++, --i)
                {
                    ;
                }

                start  = fileContents.NthIndexOfCharInString('\n', node.OriginalLine);
                start += node.OriginalColumn;

                item = styleSheet.ItemAfterPosition(start);

                if (item == null)
                {
                    continue;
                }

                while (item.TreeDepth > targetDepth)
                {
                    item = item.Parent;
                }

                // selector = item.FindType<RuleSet>().Selectors.First();

                RuleSet       rule;
                ScssRuleBlock scssRuleBlock = item as ScssRuleBlock;

                rule = scssRuleBlock == null ? item as RuleSet : scssRuleBlock.RuleSets.FirstOrDefault();

                if (rule == null)
                {
                    continue;
                }

                // Because even on the same TreeDepth, there may be mulitple ruleblocks
                // and the selector names may include & or other symbols which are diff
                // fromt he generated counterpart, here is the guess work
                item = rule.Children.FirstOrDefault(r => r is Selector && r.Text.Trim() == simpleText) as Selector;

                selector = item == null ? null : item as Selector;

                if (selector == null)
                {
                    // One more try: look for the selector in neighboring rule blocks then skip.
                    selector = rule.Children.Where(r => r is RuleBlock)
                               .SelectMany(r => (r as RuleBlock).Children
                                           .Where(s => s is RuleSet)
                                           .Select(s => (s as RuleSet).Selectors.FirstOrDefault(sel => sel.Text.Trim() == simpleText)))
                               .FirstOrDefault();

                    if (selector == null)
                    {
                        continue;
                    }
                }

                node.OriginalLine   = fileContents.Substring(0, selector.Start).Count(s => s == '\n');
                node.OriginalColumn = fileContents.GetLineColumn(selector.Start, node.OriginalLine);

                result.Add(node);
            }

            return(result);
        }
        private IEnumerable <CssSourceMapNode> ProcessGeneratedMaps(string cssfileContents)
        {
            ParseItem      item       = null;
            Selector       selector   = null;
            StyleSheet     styleSheet = null;
            SimpleSelector simple     = null;
            int            start;
            var            parser = new CssParser();
            var            result = new List <CssSourceMapNode>();

            styleSheet = parser.Parse(cssfileContents, false);

            foreach (var node in MapNodes)
            {
                start  = cssfileContents.NthIndexOfCharInString('\n', node.GeneratedLine);
                start += node.GeneratedColumn;

                item = styleSheet.ItemAfterPosition(start);

                if (item == null)
                {
                    continue;
                }

                selector = item.FindType <Selector>();

                if (selector == null)
                {
                    continue;
                }

                var depth = node.OriginalSelector.TreeDepth / 2;

                if (depth < selector.SimpleSelectors.Count)
                {
                    simple = selector.SimpleSelectors.First();

                    if (simple == null)
                    {
                        simple = item.Parent != null?item.Parent.FindType <SimpleSelector>() : null;
                    }

                    if (simple == null)
                    {
                        continue;
                    }

                    var selectorText = new StringBuilder();

                    for (int i = 0; i < node.OriginalSelector.SimpleSelectors.Count; i++)
                    {
                        if (simple == null)
                        {
                            break;
                        }

                        selectorText.Append(simple.Text).Append(" ");

                        simple = simple.NextSibling as SimpleSelector;
                    }

                    StyleSheet sheet = parser.Parse(selectorText.ToString(), false);

                    if (sheet == null || !sheet.RuleSets.Any() || !sheet.RuleSets.First().Selectors.Any())
                    {
                        continue;
                    }

                    selector = sheet.RuleSets.First().Selectors.First() as Selector;

                    if (selector == null)
                    {
                        continue;
                    }
                }

                node.GeneratedSelector = selector;

                result.Add(node);
            }

            return(result);
        }
Exemple #35
0
        private static UnitType GetUnitType(ParseItem valueItem)
        {
            UnitValue unitValue = valueItem as UnitValue;

            return((unitValue != null) ? unitValue.UnitType : UnitType.Unknown);
        }
 protected abstract string GetLabel(ParseItem item);
        internal virtual bool IsValidBeforeFirstImport(ParseItem item)
        {
            // @imports have to be at the top (ignoring comments and @charset).

            return(item is Comment || item is CharsetDirective);
        }
 /// <summary>
 /// This is for finding @imports that are only valid in the editor
 /// </summary>
 internal virtual bool IsReferenceComment(ParseItem item, out string importPath)
 {
     importPath = string.Empty;
     return(false);
 }
 /// <summary>
 /// import can be null
 /// </summary>
 internal virtual IEnumerable <string> TransformImportFile(ParseItem originalFileItem, string fileName)
 {
     return(new string[] { fileName });
 }
        /// <summary>
        /// This helps the ColorParser class to figure out the values of each color argument.
        /// If the output argumentValue is float.NaN then the argument can still be valid, but
        /// its actualy value cannot be determined.
        /// </summary>
        internal virtual bool GetColorArgumentValue(int argumentIndex, bool looseParsing, out float argumentValue)
        {
            argumentValue = 0;

            FunctionArgument colorArgument = (argumentIndex >= 0 && argumentIndex < Arguments.Count)
                ? Arguments[argumentIndex] as FunctionArgument
                : null;

            // Make sure the argument has the right number of children

            if (colorArgument == null ||
                colorArgument.ArgumentItems.Count == 0 ||
                (!looseParsing && colorArgument.ArgumentItems.Count != 1))
            {
                return(false);
            }

            ParseItem colorNumber = colorArgument.ArgumentItems[0];
            UnitType  unitType    = PropertyValueHelpers.GetUnitType(colorNumber);

            if (argumentIndex > 3)
            {
                // No color function has more than four arguments
                return(false);
            }
            else if (argumentIndex == 3)
            {
                // It's the alpha value
                if (ColorFunction == ColorFunctionType.Rgba || ColorFunction == ColorFunctionType.Hsla)
                {
                    if (PropertyValueHelpers.IsValidNumber(colorNumber))
                    {
                        if (float.TryParse(colorNumber.Text, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out argumentValue))
                        {
                            return(true);
                        }
                    }
                }
            }
            else if (ColorFunction == ColorFunctionType.Rgb || ColorFunction == ColorFunctionType.Rgba)
            {
                // Red, Green, and Blue are always a <percentage> or <integer>

                if (unitType == UnitType.Percentage)
                {
                    if (float.TryParse(colorNumber.Text.TrimEnd('%'), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out argumentValue))
                    {
                        argumentValue /= 100.0f;
                        return(true);
                    }
                }
                else if (PropertyValueHelpers.IsValidInteger(colorNumber))
                {
                    if (int.TryParse(colorNumber.Text, out int intValue))
                    {
                        argumentValue = intValue / 255.0f;
                        return(true);
                    }
                }
            }
            else if (argumentIndex == 0)
            {
                // Hue is always a <number>

                if (PropertyValueHelpers.IsValidNumber(colorNumber))
                {
                    if (float.TryParse(colorNumber.Text, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out argumentValue))
                    {
                        argumentValue /= 360.0f;
                        return(true);
                    }
                }
            }
            else
            {
                // Saturation and Lightness are always a percentage

                if (unitType == UnitType.Percentage)
                {
                    if (float.TryParse(colorNumber.Text.TrimEnd('%'), NumberStyles.Number, NumberFormatInfo.InvariantInfo, out argumentValue))
                    {
                        argumentValue /= 100.0f;
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #41
0
        // parse a component of the expanded set.
        // At this point, no pattern may contain "/" in it
        // so we're going to return a 2d array, where each entry is the full
        // pattern, split on '/', and then turned into a regular expression.
        // A regexp is made at the end which joins each array with an
        // escaped /, and another full one which joins each regexp with |.
        //
        // Following the lead of Bash 4.1, note that "**" only has special meaning
        // when it is the *only* thing in a path portion.  Otherwise, any series
        // of * is equivalent to a single *.  Globstar behavior is enabled by
        // default, and can be disabled by setting options.noglobstar.
        private Tuple <ParseItem, bool> Parse(string pattern, bool isSub)
        {
            // shortcuts
            if (!options.NoGlobStar && pattern == "**")
            {
                return(Tuple.Create(GlobStar.Instance, false));
            }
            if (pattern == "")
            {
                return(Tuple.Create(ParseItem.Empty, false));
            }

            string re = "";
            bool   hasMagic = options.NoCase, escaping = false, inClass = false;
            // ? => one single character
            var  patternListStack = new Stack <PatternListEntry>();
            char plType;
            char?stateChar = null;

            int reClassStart = -1, classStart = -1;
            // . and .. never match anything that doesn't start with .,
            // even when options.dot is set.
            string patternStart = pattern[0] == '.' ? "" // anything
                                                         // not (start or / followed by . or .. followed by / or end)
              : options.Dot ? "(?!(?:^|\\/)\\.{1,2}(?:$|\\/))"
              : "(?!\\.)";

            Action clearStateChar = () =>
            {
                if (stateChar != null)
                {
                    // we had some state-tracking character
                    // that wasn't consumed by this pass.
                    switch (stateChar)
                    {
                    case '*':
                        re      += star;
                        hasMagic = true;
                        break;

                    case '?':
                        re      += qmark;
                        hasMagic = true;
                        break;

                    default:
                        re += "\\" + stateChar;
                        break;
                    }
                    stateChar = null;
                }
            };

            for (var i = 0; i < pattern.Length; i++)
            {
                var c = pattern[i];
                //if (options.debug) {
                //  console.error("%s\t%s %s %j", pattern, i, re, c)
                //}

                // skip over any that are escaped.
                if (escaping && reSpecials.Contains(c))
                {
                    re      += "\\" + c;
                    escaping = false;
                    continue;
                }

                switch (c)
                {
                case '/':
                    // completely not allowed, even escaped.
                    // Should already be path-split by now.
                    return(null);

                case '\\':
                    clearStateChar();
                    escaping = true;
                    continue;

                // the various stateChar values
                // for the 'extglob' stuff.
                case '?':
                case '*':
                case '+':
                case '@':
                case '!':
                    //if (options.debug) {
                    //  console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
                    //}

                    // all of those are literals inside a class, except that
                    // the glob [!a] means [^a] in regexp
                    if (inClass)
                    {
                        if (c == '!' && i == classStart + 1)
                        {
                            c = '^';
                        }
                        re += c;
                        continue;
                    }

                    // if we already have a stateChar, then it means
                    // that there was something like ** or +? in there.
                    // Handle the stateChar, then proceed with this one.
                    clearStateChar();
                    stateChar = c;
                    // if extglob is disabled, then +(asdf|foo) isn't a thing.
                    // just clear the statechar *now*, rather than even diving into
                    // the patternList stuff.
                    if (options.NoExt)
                    {
                        clearStateChar();
                    }
                    continue;

                case '(':
                    if (inClass)
                    {
                        re += "(";
                        continue;
                    }

                    if (stateChar == null)
                    {
                        re += "\\(";
                        continue;
                    }

                    plType = stateChar.Value;
                    patternListStack.Push(new PatternListEntry {
                        Type = plType, Start = i - 1, ReStart = re.Length
                    });
                    // negation is (?:(?!js)[^/]*)
                    re       += stateChar == '!' ? "(?:(?!" : "(?:";
                    stateChar = null;
                    continue;

                case ')':
                    if (inClass || !patternListStack.Any())
                    {
                        re += "\\)";
                        continue;
                    }

                    hasMagic = true;
                    re      += ')';
                    plType   = patternListStack.Pop().Type;
                    // negation is (?:(?!js)[^/]*)
                    // The others are (?:<pattern>)<type>
                    switch (plType)
                    {
                    case '!':
                        re += "[^/]*?)";
                        break;

                    case '?':
                    case '+':
                    case '*': re += plType; break;

                    case '@': break;         // the default anyway
                    }
                    continue;

                case '|':
                    if (inClass || !patternListStack.Any() || escaping)
                    {
                        re      += "\\|";
                        escaping = false;
                        continue;
                    }

                    re += "|";
                    continue;

                // these are mostly the same in regexp and glob
                case '[':
                    // swallow any state-tracking char before the [
                    clearStateChar();

                    if (inClass)
                    {
                        re += "\\" + c;
                        continue;
                    }

                    inClass      = true;
                    classStart   = i;
                    reClassStart = re.Length;
                    re          += c;
                    continue;

                case ']':
                    //  a right bracket shall lose its special
                    //  meaning and represent itself in
                    //  a bracket expression if it occurs
                    //  first in the list.  -- POSIX.2 2.8.3.2
                    if (i == classStart + 1 || !inClass)
                    {
                        re      += "\\" + c;
                        escaping = false;
                        continue;
                    }

                    // finish up the class.
                    hasMagic = true;
                    inClass  = false;
                    re      += c;
                    continue;

                default:
                    // swallow any state char that wasn't consumed
                    clearStateChar();

                    if (escaping)
                    {
                        // no need
                        escaping = false;
                    }
                    else if (reSpecials.Contains(c) && !(c == '^' && inClass))
                    {
                        re += "\\";
                    }

                    re += c;
                    break;
                } // switch
            }     // for


            // handle the case where we left a class open.
            // "[abc" is valid, equivalent to "\[abc"
            if (inClass)
            {
                // split where the last [ was, and escape it
                // this is a huge pita.  We now have to re-walk
                // the contents of the would-be class to re-translate
                // any characters that were passed through as-is
                string cs = pattern.Substring(classStart + 1);
                var    sp = this.Parse(cs, true);
                re       = re.Substring(0, reClassStart) + "\\[" + sp.Item1.Source;
                hasMagic = hasMagic || sp.Item2;
            }

            // handle the case where we had a +( thing at the *end*
            // of the pattern.
            // each pattern list stack adds 3 chars, and we need to go through
            // and escape any | chars that were passed through as-is for the regexp.
            // Go through and escape them, taking care not to double-escape any
            // | chars that were already escaped.
            while (patternListStack.Any())
            {
                var pl   = patternListStack.Pop();
                var tail = re.Substring(pl.ReStart + 3);
                // maybe some even number of \, then maybe 1 \, followed by a |
                tail = escapeCheck.Replace(tail, m =>
                {
                    string escape = m.Groups[2].Value;
                    // the | isn't already escaped, so escape it.
                    if (String.IsNullOrEmpty(escape))
                    {
                        escape = "\\";
                    }

                    // need to escape all those slashes *again*, without escaping the
                    // one that we need for escaping the | character.  As it works out,
                    // escaping an even number of slashes can be done by simply repeating
                    // it exactly after itself.  That's why this trick works.
                    //
                    // I am sorry that you have to see this.
                    return(m.Groups[1].Value + m.Groups[1].Value + escape + "|");
                });

                // console.error("tail=%j\n   %s", tail, tail)
                var t = pl.Type == '*' ? star
                      : pl.Type == '?' ? qmark
                      : "\\" + pl.Type;

                hasMagic = true;
                re       = re.Remove(pl.ReStart)
                           + t + "\\("
                           + tail;
            }

            // handle trailing things that only matter at the very end.
            clearStateChar();
            if (escaping)
            {
                // trailing \\
                re += "\\\\";
            }

            // only need to apply the nodot start if the re starts with
            // something that could conceivably capture a dot
            var addPatternStart = false;

            switch (re[0])
            {
            case '.':
            case '[':
            case '(': addPatternStart = true; break;
            }

            // if the re is not "" at this point, then we need to make sure
            // it doesn't match against an empty path part.
            // Otherwise a/* will match a/, which it should not.
            if (re != "" && hasMagic)
            {
                re = "(?=.)" + re;
            }

            if (addPatternStart)
            {
                re = patternStart + re;
            }

            // parsing just a piece of a larger pattern.
            if (isSub)
            {
                return(Tuple.Create(ParseItem.Literal(re), hasMagic));
            }

            // skip the regexp for non-magical patterns
            // unescape anything in it, though, so that it'll be
            // an exact match against a file etc.
            if (!hasMagic)
            {
                return(Tuple.Create(ParseItem.Literal(GlobUnescape(pattern)), false));
            }
            return(new Tuple <ParseItem, bool>(new MagicItem(re, options), false));
        }
Exemple #42
0
        // set partial to true to test if, for example,
        // "/a/b" matches the start of "/*/b/*/d"
        // Partial means, if you run out of file before you run
        // out of pattern, then that's fine, as long as all
        // the parts match.
        bool MatchOne(IList <string> file, IList <ParseItem> pattern, bool partial)
        {
            //if (options.debug) {
            //  console.error("matchOne",
            //                { "this": this
            //                , file: file
            //                , pattern: pattern })
            //}

            if (options.MatchBase && pattern.Count == 1)
            {
                file = new[] { file.Last(s => !String.IsNullOrEmpty(s)) };
            }

            //if (options.debug) {
            //  console.error("matchOne", file.length, pattern.length)
            //}
            int fi = 0, pi = 0;

            for (; (fi < file.Count) && (pi < pattern.Count); fi++, pi++)
            {
                //if (options.debug) {
                //  console.error("matchOne loop")
                //}
                ParseItem p = pattern[pi];
                string    f = file[fi];

                //if (options.debug) {
                //  console.error(pattern, p, f)
                //}

                // should be impossible.
                // some invalid regexp stuff in the set.
                if (p == null)
                {
                    return(false);
                }

                if (p is GlobStar)
                {
                    //if (options.debug)
                    //  console.error('GLOBSTAR', [pattern, p, f])

                    // "**"
                    // a/**/b/**/c would match the following:
                    // a/b/x/y/z/c
                    // a/x/y/z/b/c
                    // a/b/x/b/x/c
                    // a/b/c
                    // To do this, take the rest of the pattern after
                    // the **, and see if it would match the file remainder.
                    // If so, return success.
                    // If not, the ** "swallows" a segment, and try again.
                    // This is recursively awful.
                    //
                    // a/**/b/**/c matching a/b/x/y/z/c
                    // - a matches a
                    // - doublestar
                    //   - matchOne(b/x/y/z/c, b/**/c)
                    //     - b matches b
                    //     - doublestar
                    //       - matchOne(x/y/z/c, c) -> no
                    //       - matchOne(y/z/c, c) -> no
                    //       - matchOne(z/c, c) -> no
                    //       - matchOne(c, c) yes, hit
                    int fr = fi, pr = pi + 1;
                    if (pr == pattern.Count)
                    {
                        //if (options.debug)
                        //  console.error('** at the end')
                        // a ** at the end will just swallow the rest.
                        // We have found a match.
                        // however, it will not swallow /.x, unless
                        // options.dot is set.
                        // . and .. are *never* matched by **, for explosively
                        // exponential reasons.
                        for (; fi < file.Count; fi++)
                        {
                            if (file[fi] == "." || file[fi] == ".." ||
                                (!options.Dot && !string.IsNullOrEmpty(file[fi]) && file[fi][0] == '.'))
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }

                    // ok, let's see if we can swallow whatever we can.
                    while (fr < file.Count)
                    {
                        var swallowee = file[fr];

                        //if (options.debug) {
                        //  console.error('\nglobstar while',
                        //                file, fr, pattern, pr, swallowee)
                        //}

                        // XXX remove this slice.  Just pass the start index.
                        if (this.MatchOne(file.Skip(fr).ToList(), pattern.Skip(pr).ToList(), partial))
                        {
                            //if (options.debug)
                            //  console.error('globstar found match!', fr, file.Count, swallowee)
                            // found a match.
                            return(true);
                        }
                        else
                        {
                            // can't swallow "." or ".." ever.
                            // can only swallow ".foo" when explicitly asked.
                            if (swallowee == "." || swallowee == ".." ||
                                (!options.Dot && swallowee[0] == '.'))
                            {
                                //if (options.debug)
                                //  console.error("dot detected!", file, fr, pattern, pr)
                                break;
                            }

                            // ** swallows a segment, and continue.
                            //if (options.debug)
                            //  console.error('globstar swallow a segment, and continue')
                            fr++;
                        }
                    }
                    // no match was found.
                    // However, in partial mode, we can't say this is necessarily over.
                    // If there's more *pattern* left, then
                    if (partial)
                    {
                        // ran out of file
                        // console.error("\n>>> no match, partial?", file, fr, pattern, pr)
                        if (fr == file.Count)
                        {
                            return(true);
                        }
                    }
                    return(false);
                }

                // something other than **
                // non-magic patterns just have to match exactly
                // patterns with magic have been turned into regexps.
                if (!p.Match(f, options))
                {
                    return(false);
                }
            }

            // Note: ending in / means that we'll get a final ""
            // at the end of the pattern.  This can only match a
            // corresponding "" at the end of the file.
            // If the file ends in /, then it can only match a
            // a pattern that ends in /, unless the pattern just
            // doesn't have any more for it. But, a/b/ should *not*
            // match "a/b/*", even though "" matches against the
            // [^/]*? pattern, except in partial mode, where it might
            // simply not be reached yet.
            // However, a/b/ should still satisfy a/*

            // now either we fell off the end of the pattern, or we're done.
            if (fi == file.Count && pi == pattern.Count)
            {
                // ran out of pattern and filename at the same time.
                // an exact hit!
                return(true);
            }
            else if (fi == file.Count)
            {
                // ran out of file, but still had pattern left.
                // this is ok if we're doing the match as part of
                // a glob fs traversal.
                return(partial);
            }
            else if (pi == pattern.Count)
            {
                // ran out of pattern, still have file left.
                // this is only acceptable if we're on the very last
                // empty segment of a file with a trailing slash.
                // a/* should match a/b/
                var emptyFileEnd = (fi == file.Count - 1) && (file[fi] == "");
                return(emptyFileEnd);
            }

            // should be unreachable.
            throw new InvalidOperationException("wtf?");
        }
Exemple #43
0
 public ReadOnlyCollection <TResult> Crawl(ParseItem root)
 {
     root.Accept(this);
     return(Items);
 }
Exemple #44
0
        void MapCallBack(ParseItem drop)
        {
            Intent dropAC = new Intent(this, typeof(NearbyActivity));

            StartActivity(dropAC);
        }
Exemple #45
0
        private static Tuple <ParseItem, ICssCompletionListEntry> GetEntriesAndPoint(ParseItem item, SnapshotPoint point, ICssSchemaInstance schema)
        {
            // Declaration
            Declaration dec = item.FindType <Declaration>();

            if (dec != null && dec.PropertyName != null && dec.PropertyName.ContainsRange(point.Position, 1))
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(dec.PropertyName, schema.GetProperty(dec.PropertyName.Text)));
            }

            if (dec != null && dec.IsValid && dec.Values.TextStart <= point.Position && dec.Values.TextAfterEnd >= point.Position)
            {
                var entry = schema.GetProperty(dec.PropertyName.Text);

                if (entry != null)
                {
                    var list   = schema.GetPropertyValues(entry.DisplayText);
                    var theOne = dec.StyleSheet.ItemFromRange(point.Position, 0);

                    return(Tuple.Create <ParseItem, ICssCompletionListEntry>(theOne,
                                                                             list.SingleOrDefault(r => r.DisplayText.Equals(theOne.Text, StringComparison.OrdinalIgnoreCase))));
                }
            }

            // Pseudo class
            PseudoClassSelector pseudoClass = item.FindType <PseudoClassSelector>();

            if (pseudoClass != null)
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(pseudoClass, schema.GetPseudo(pseudoClass.Text)));
            }

            // Pseudo class function
            PseudoClassFunctionSelector pseudoClassFunction = item.FindType <PseudoClassFunctionSelector>();

            if (pseudoClassFunction != null)
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(pseudoClassFunction, schema.GetPseudo(pseudoClassFunction.Text)));
            }

            // Pseudo element
            PseudoElementSelector pseudoElement = item.FindType <PseudoElementSelector>();

            if (pseudoElement != null)
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(pseudoElement, schema.GetPseudo(pseudoElement.Text)));
            }

            // Pseudo element function
            PseudoElementFunctionSelector pseudoElementFunction = item.FindType <PseudoElementFunctionSelector>();

            if (pseudoElementFunction != null)
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(pseudoElementFunction, schema.GetPseudo(pseudoElementFunction.Text)));
            }

            // @-directive
            AtDirective atDirective = item.Parent as AtDirective;

            if (atDirective != null && atDirective.Keyword != null)
            {
                return(Tuple.Create <ParseItem, ICssCompletionListEntry>(atDirective.Keyword, schema.GetAtDirective("@" + atDirective.Keyword.Text)));
            }

            return(null);
        }
Exemple #46
0
        private async Task UpdateEmbeddedImageValues(ParseItem item)
        {
            if (!WESettings.Instance.Css.SyncBase64ImageValues)
            {
                return;
            }

            Declaration dec = item.FindType <Declaration>();

            if (dec != null && Cache.Contains(dec))
            {
                var url = dec.Values.FirstOrDefault() as UrlItem;

                if (url == null || !url.IsValid || url.UrlString == null || url.UrlString.Text.Contains(";base64,"))
                {
                    return;
                }

                var matches = Cache.Where(d => d.IsValid && d != dec && d.Parent == dec.Parent &&
                                          (d.Values[0].NextSibling as CComment) != null);

                // Undo sometimes messes with the positions, so we have to make this check before proceeding.
                if (!matches.Any() || dec.Text.Length < dec.Colon.AfterEnd - dec.Start || dec.Colon.AfterEnd < dec.Start)
                {
                    return;
                }

                string urlText    = url.UrlString.Text.Trim('\'', '"');
                string filePath   = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(_buffer.GetFileName()), urlText));
                string b64UrlText = await FileHelpers.ConvertToBase64(filePath);

                string b64Url = url.Text.Replace(urlText, b64UrlText);
                IEnumerable <Tuple <SnapshotSpan, string> > changes = matches.Reverse().SelectMany(match =>
                {
                    ParseItem value  = match.Values[0];
                    CComment comment = value.NextSibling as CComment;

                    SnapshotSpan span = new SnapshotSpan(_buffer.CurrentSnapshot, comment.CommentText.Start, comment.CommentText.Length);

                    url = value as UrlItem;

                    if (url == null)
                    {
                        return(null);
                    }

                    SnapshotSpan b64Span = new SnapshotSpan(_buffer.CurrentSnapshot, url.Start, url.Length);

                    return(new[] { new Tuple <SnapshotSpan, string>(span, urlText), new Tuple <SnapshotSpan, string>(b64Span, b64Url) });
                });

                await Dispatcher.CurrentDispatcher.InvokeAsync(() =>
                {
                    using (ITextEdit edit = _buffer.CreateEdit())
                    {
                        foreach (Tuple <SnapshotSpan, string> change in changes)
                        {
                            SnapshotSpan currentSpan = change.Item1.TranslateTo(_buffer.CurrentSnapshot, SpanTrackingMode.EdgeExclusive);
                            edit.Replace(currentSpan, change.Item2);
                        }

                        edit.Apply();
                    }
                });
            }
        }
        internal static ParseItem ParsePropertyValue(ComplexItem parent, ItemFactory itemFactory, ITextProvider text, TokenStream tokens, bool callExternalFactory)
        {
            ParseItem pv    = null;
            CssToken  token = tokens.CurrentToken;

            // First give opportunity to override property value parsing
            if (callExternalFactory)
            {
                pv = itemFactory.Create <UnknownPropertyValue>(parent);
            }

            if (pv == null || pv.GetType() == typeof(UnknownPropertyValue))
            {
                switch (token.TokenType)
                {
                case CssTokenType.HashName:
                    pv = itemFactory.Create <HexColorValue>(parent);
                    break;

                case CssTokenType.Number:
                    pv = NumericalValue.ParseNumber(parent, itemFactory, text, tokens);
                    return(pv);

                case CssTokenType.Url:
                case CssTokenType.UnquotedUrlString:
                    pv = itemFactory.Create <UrlItem>(parent);
                    break;

                case CssTokenType.Function:
                    pv = Function.ParseFunction(parent, itemFactory, text, tokens);
                    return(pv);

                case CssTokenType.UnicodeRange:
                    pv = new TokenItem(tokens.CurrentToken, CssClassifierContextType.UnicodeRange);
                    break;

                case CssTokenType.Comma:
                case CssTokenType.Slash:
                    pv = new TokenItem(tokens.CurrentToken, CssClassifierContextType.Punctuation);
                    break;

                case CssTokenType.String:
                case CssTokenType.MultilineString:
                case CssTokenType.InvalidString:
                    pv = new TokenItem(tokens.CurrentToken, CssClassifierContextType.String);
                    break;

                case CssTokenType.Identifier:
                    pv = new TokenItem(tokens.CurrentToken, null);
                    break;

                case CssTokenType.OpenSquareBracket:
                case CssTokenType.OpenFunctionBrace:
                case CssTokenType.OpenCurlyBrace:
                    // "grid-rows" uses square brackets - http://dev.w3.org/csswg/css3-grid/
                    // And this is from a Win8 spec: -ms-grid-columns: (200px 10px)[3];
                    // Also, custom property values may have curly brace blocks
                    pv = itemFactory.Create <PropertyValueBlock>(parent);
                    break;

                default:
                    if (callExternalFactory)
                    {
                        pv = itemFactory.Create <UnknownPropertyValue>(parent);

                        if (pv.GetType() == typeof(UnknownPropertyValue))
                        {
                            // UnknownPropertyValue is just a placeholder for plugins to use.
                            // If one is actually created, discard it.
                            pv = null;
                        }
                    }
                    break;
                }
            }

            if (pv != null)
            {
                if (!pv.Parse(itemFactory, text, tokens))
                {
                    pv = null;
                }
            }

            return(pv);
        }
Exemple #48
0
        public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> qiContent, out ITrackingSpan applicableToSpan)
        {
            applicableToSpan = null;

            if (session == null || qiContent == null || qiContent.Count > 0 || !WESettings.Instance.Css.ShowBrowserTooltip)
            {
                return;
            }

            SnapshotPoint?point = session.GetTriggerPoint(_buffer.CurrentSnapshot);

            if (!point.HasValue)
            {
                return;
            }

            var       tree = CssEditorDocument.FromTextBuffer(_buffer);
            ParseItem item = tree.StyleSheet.ItemBeforePosition(point.Value.Position);

            if (item == null || !item.IsValid)
            {
                return;
            }

            ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(_rootSchema, item);

            Tuple <ParseItem, ICssCompletionListEntry> tuple = GetEntriesAndPoint(item, point.Value, schema);

            if (tuple == null)
            {
                return;
            }

            ParseItem tipItem             = tuple.Item1;
            ICssCompletionListEntry entry = tuple.Item2;

            if (tipItem == null || entry == null)
            {
                return;
            }

            var ruleSet = item.FindType <RuleSet>();

            //If the selector's full name would require computation (it's nested), compute it and add it to the output
            if (ruleSet != null && ruleSet.Parent.FindType <RuleSet>() != null)
            {
                qiContent.Add(LessDocument.GetLessSelectorName(ruleSet));
            }

            applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(tipItem.Start, tipItem.Length, SpanTrackingMode.EdgeNegative);

            string syntax = entry.GetSyntax(schema.Version);
            string b      = entry.GetAttribute("browsers");

            if (string.IsNullOrEmpty(b) && tipItem.Parent != null && tipItem.Parent is Declaration)
            {
                b = schema.GetProperty(((Declaration)tipItem.Parent).PropertyName.Text).GetAttribute("browsers");
                if (string.IsNullOrEmpty(syntax))
                {
                    syntax = tipItem.Text;
                }
            }

            if (!string.IsNullOrEmpty(syntax))
            {
                //var example = CreateExample(syntax);
                qiContent.Add("Example: " + syntax);
            }

            Dictionary <string, string> browsers = GetBrowsers(b);

            qiContent.Add(CreateBrowserList(browsers));
        }
 internal static UnitType GetUnitType(ParseItem valueItem)
 {
     return((valueItem is UnitValue unitValue) ? unitValue.UnitType : UnitType.Unknown);
 }
Exemple #50
0
        public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> qiContent, out ITrackingSpan applicableToSpan)
        {
            applicableToSpan = null;

            if (!EnsureTreeInitialized() || session == null || qiContent == null || qiContent.Count > 0 || !WESettings.GetBoolean(WESettings.Keys.ShowBrowserTooltip))
            {
                return;
            }

            SnapshotPoint?point = session.GetTriggerPoint(_buffer.CurrentSnapshot);

            if (!point.HasValue)
            {
                return;
            }

            ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position);

            if (item == null || !item.IsValid)
            {
                return;
            }

            ParseItem theOne = null;
            ICssCompletionListEntry entry  = null;
            ICssSchemaInstance      schema = CssSchemaManager.SchemaManager.GetSchemaForItem(_rootSchema, item);

            // Declaration
            Declaration dec = item.FindType <Declaration>();

            if (dec != null && dec.PropertyName != null && dec.PropertyName.ContainsRange(point.Value.Position, 1))
            {
                entry  = schema.GetProperty(dec.PropertyName.Text);
                theOne = dec.PropertyName;
            }
            else if (dec != null && dec.IsValid && dec.Values.TextStart <= point.Value.Position && dec.Values.TextAfterEnd >= point.Value.Position)
            {
                entry = schema.GetProperty(dec.PropertyName.Text);
                if (entry != null)
                {
                    var list = schema.GetPropertyValues(entry.DisplayText);
                    theOne = dec.StyleSheet.ItemFromRange(point.Value.Position, 0);
                    entry  = list.SingleOrDefault(r => r.DisplayText.Equals(theOne.Text, StringComparison.OrdinalIgnoreCase));
                }
            }

            // Pseudo class
            if (entry == null)
            {
                PseudoClassSelector pseudoClass = item.FindType <PseudoClassSelector>();
                if (pseudoClass != null)
                {
                    entry  = schema.GetPseudo(pseudoClass.Text);
                    theOne = pseudoClass;
                }
            }

            // Pseudo class function
            if (entry == null)
            {
                PseudoClassFunctionSelector pseudoClassFunction = item.FindType <PseudoClassFunctionSelector>();
                if (pseudoClassFunction != null)
                {
                    entry  = schema.GetPseudo(pseudoClassFunction.Text);
                    theOne = pseudoClassFunction;
                }
            }

            // Pseudo element
            if (entry == null)
            {
                PseudoElementSelector pseudoElement = item.FindType <PseudoElementSelector>();
                if (pseudoElement != null)
                {
                    entry  = schema.GetPseudo(pseudoElement.Text);
                    theOne = pseudoElement;
                }
            }

            // Pseudo element function
            if (entry == null)
            {
                PseudoElementFunctionSelector pseudoElementFunction = item.FindType <PseudoElementFunctionSelector>();
                if (pseudoElementFunction != null)
                {
                    entry  = schema.GetPseudo(pseudoElementFunction.Text);
                    theOne = pseudoElementFunction;
                }
            }

            // @-directive
            if (entry == null)
            {
                AtDirective atDirective = item.Parent as AtDirective;
                if (atDirective != null && atDirective.Keyword != null)
                {
                    entry  = schema.GetAtDirective("@" + atDirective.Keyword.Text);
                    theOne = atDirective.Keyword;
                }
            }

            if (entry != null)
            {
                applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(theOne.Start, theOne.Length, SpanTrackingMode.EdgeNegative);

                string syntax = entry.GetSyntax(schema.Version);
                string b      = entry.GetAttribute("browsers");

                if (string.IsNullOrEmpty(b) && theOne.Parent != null && theOne.Parent is Declaration)
                {
                    b = schema.GetProperty(((Declaration)theOne.Parent).PropertyName.Text).GetAttribute("browsers");
                    if (string.IsNullOrEmpty(syntax))
                    {
                        syntax = theOne.Text;
                    }
                }

                if (!string.IsNullOrEmpty(syntax))
                {
                    //var example = CreateExample(syntax);
                    qiContent.Add("Example: " + syntax);
                }

                Dictionary <string, string> browsers = GetBrowsers(b);
                qiContent.Add(CreateBrowserList(browsers));
            }
        }