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); } }
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); }
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); }
// 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)); }
// 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?"); }
public ReadOnlyCollection <TResult> Crawl(ParseItem root) { root.Accept(this); return(Items); }
void MapCallBack(ParseItem drop) { Intent dropAC = new Intent(this, typeof(NearbyActivity)); StartActivity(dropAC); }
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); }
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); }
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); }
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)); } }