public void GetAttributeNameValuePairs_ParsesPairsCorrectly( string documentContent, IEnumerable<KeyValuePair<string, string>> expectedPairs) { // Arrange var errorSink = new ErrorSink(); var parseResult = ParseDocument(documentContent, errorSink); var document = parseResult.Document; var rewriters = RazorParser.GetDefaultRewriters(new HtmlMarkupParser()); var rewritingContext = new RewritingContext(document, errorSink); foreach (var rewriter in rewriters) { rewriter.Rewrite(rewritingContext); } var block = rewritingContext.SyntaxTree.Children.First(); var parseTreeRewriter = new TagHelperParseTreeRewriter(provider: null); // Assert - Guard var tagBlock = Assert.IsType<Block>(block); Assert.Equal(BlockType.Tag, tagBlock.Type); Assert.Empty(errorSink.Errors); // Act var pairs = parseTreeRewriter.GetAttributeNameValuePairs(tagBlock); // Assert Assert.Equal(expectedPairs, pairs); }
/// <summary> /// Instantiates a new <see cref="ParserResults"/> instance. /// </summary> /// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param> /// <param name="document">The <see cref="Block"/> for the syntax tree.</param> /// <param name="tagHelperDescriptors"> /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document. /// </param> /// <param name="errorSink"> /// The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the /// current Razor document. /// </param> protected ParserResults(bool success, Block document, IEnumerable<TagHelperDescriptor> tagHelperDescriptors, ErrorSink errorSink) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (tagHelperDescriptors == null) { throw new ArgumentNullException(nameof(tagHelperDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } Success = success; Document = document; TagHelperDescriptors = tagHelperDescriptors; ErrorSink = errorSink; ParserErrors = errorSink.Errors; Prefix = tagHelperDescriptors.FirstOrDefault()?.Prefix; }
/// <summary> /// Instantiates a new <see cref="RewritingContext"/>. /// </summary> public RewritingContext(Block syntaxTree, ErrorSink errorSink) { _errors = new List<RazorError>(); SyntaxTree = syntaxTree; ErrorSink = errorSink; }
/// <summary> /// Creates a <see cref="TagHelperDescriptor"/> from the given <paramref name="typeInfo"/>. /// </summary> /// <param name="assemblyName">The assembly name that contains <paramref name="type"/>.</param> /// <param name="typeInfo">The <see cref="ITypeInfo"/> to create a <see cref="TagHelperDescriptor"/> from. /// </param> /// <param name="errorSink">The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered /// when creating <see cref="TagHelperDescriptor"/>s for the given <paramref name="typeInfo"/>.</param> /// <returns> /// A collection of <see cref="TagHelperDescriptor"/>s that describe the given <paramref name="typeInfo"/>. /// </returns> public virtual IEnumerable<TagHelperDescriptor> CreateDescriptors( string assemblyName, ITypeInfo typeInfo, ErrorSink errorSink) { if (typeInfo == null) { throw new ArgumentNullException(nameof(typeInfo)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (ShouldSkipDescriptorCreation(typeInfo)) { return Enumerable.Empty<TagHelperDescriptor>(); } var attributeDescriptors = GetAttributeDescriptors(typeInfo, errorSink); var targetElementAttributes = GetValidHtmlTargetElementAttributes(typeInfo, errorSink); var allowedChildren = GetAllowedChildren(typeInfo, errorSink); var tagHelperDescriptors = BuildTagHelperDescriptors( typeInfo, assemblyName, attributeDescriptors, targetElementAttributes, allowedChildren); return tagHelperDescriptors.Distinct(TagHelperDescriptorComparer.Default); }
public void CreateDescriptors_WithPrefixes_ReturnsExpectedAttributeDescriptors( Type tagHelperType, IEnumerable<TagHelperAttributeDescriptor> expectedAttributeDescriptors, string[] expectedErrorMessages) { // Arrange var errorSink = new ErrorSink(); var factory = new TagHelperDescriptorFactory(designTime: false); // Act var descriptors = factory.CreateDescriptors( AssemblyName, GetTypeInfo(tagHelperType), errorSink: errorSink); // Assert var errors = errorSink.Errors.ToArray(); Assert.Equal(expectedErrorMessages.Length, errors.Length); for (var i = 0; i < errors.Length; i++) { Assert.Equal(0, errors[i].Length); Assert.Equal(SourceLocation.Zero, errors[i].Location); Assert.Equal(expectedErrorMessages[i], errors[i].Message, StringComparer.Ordinal); } var descriptor = Assert.Single(descriptors); Assert.Equal( expectedAttributeDescriptors, descriptor.Attributes, TagHelperAttributeDescriptorComparer.Default); }
public void Resolve_CalculatesAssemblyLocationInLookupText(string lookupText, int assemblyLocation) { // Arrange var errorSink = new ErrorSink(); var tagHelperDescriptorResolver = new InspectableTagHelperDescriptorResolver(); var directiveType = TagHelperDirectiveType.AddTagHelper; var resolutionContext = new TagHelperDescriptorResolutionContext( new[] { new TagHelperDirectiveDescriptor { DirectiveText = lookupText, Location = SourceLocation.Zero, DirectiveType = directiveType } }, errorSink); var expectedSourceLocation = new SourceLocation(assemblyLocation, 0, assemblyLocation); // Act tagHelperDescriptorResolver.Resolve(resolutionContext); // Assert Assert.Empty(errorSink.Errors); Assert.Equal(expectedSourceLocation, tagHelperDescriptorResolver.DocumentLocation); }
public TagHelperDirectiveSpanVisitor( [NotNull] ITagHelperDescriptorResolver descriptorResolver, [NotNull] ErrorSink errorSink) { _descriptorResolver = descriptorResolver; _errorSink = errorSink; }
private static IEnumerable<TargetElementAttribute> GetValidTargetElementAttributes( TypeInfo typeInfo, ErrorSink errorSink) { var targetElementAttributes = typeInfo.GetCustomAttributes<TargetElementAttribute>(inherit: false); return targetElementAttributes.Where(attribute => ValidTargetElementAttributeNames(attribute, errorSink)); }
public override ParserContext CreateParserContext( ITextDocument input, ParserBase codeParser, ParserBase markupParser, ErrorSink errorSink) { return base.CreateParserContext(input, codeParser, markupParser, errorSink); }
public CompilerContext(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink, ParserSink parserSink) { Contract.RequiresNotNull(sourceUnit, "sourceUnit"); _sourceUnit = sourceUnit; _options = options ?? sourceUnit.Engine.GetDefaultCompilerOptions(); _errors = errorSink ?? sourceUnit.Engine.GetCompilerErrorSink(); _parserSink = parserSink ?? ParserSink.Null; }
public void ConstructorAcceptsActiveParserIfIsSameAsEitherCodeOrMarkupParser() { var codeParser = new CSharpCodeParser(); var markupParser = new HtmlMarkupParser(); var errorSink = new ErrorSink(); new ParserContext( new SeekableTextReader(TextReader.Null), codeParser, markupParser, codeParser, errorSink); new ParserContext( new SeekableTextReader(TextReader.Null), codeParser, markupParser, markupParser, errorSink); }
public virtual ParserContext CreateParserContext(ITextDocument input, ParserBase codeParser, ParserBase markupParser, ErrorSink errorSink) { return new ParserContext(input, codeParser, markupParser, SelectActiveParser(codeParser, markupParser), errorSink); }
public CompilerContext(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink, ParserSink parserSink) { ContractUtils.RequiresNotNull(sourceUnit, "sourceUnit"); ContractUtils.RequiresNotNull(errorSink, "errorSink"); ContractUtils.RequiresNotNull(parserSink, "parserSink"); ContractUtils.RequiresNotNull(options, "options"); _sourceUnit = sourceUnit; _options = options; _errors = errorSink; _parserSink = parserSink; }
// Internal for testing. internal CodeBuilderContext(RazorEngineHost host, string className, string rootNamespace, string sourceFile, bool shouldGenerateLinePragmas, ErrorSink errorSink) : base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas) { ErrorSink = errorSink; ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput; }
public static TagHelperBlockBuilder Rewrite( string tagName, bool validStructure, Block tag, IEnumerable<TagHelperDescriptor> descriptors, ErrorSink errorSink) { // There will always be at least one child for the '<'. var start = tag.Children.First().Start; var attributes = GetTagAttributes(tagName, validStructure, tag, descriptors, errorSink); var tagMode = GetTagMode(tagName, tag, descriptors, errorSink); return new TagHelperBlockBuilder(tagName, tagMode, start, attributes, descriptors); }
public void VisitCallsOnCompleteWhenAllNodesHaveBeenVisited() { // Arrange Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>(); var root = new BlockBuilder() { Type = BlockType.Comment }.Build(); var errorSink = new ErrorSink(); errorSink.OnError(new RazorError("Foo", new SourceLocation(1, 0, 1), length: 3)); errorSink.OnError(new RazorError("Bar", new SourceLocation(2, 0, 2), length: 3)); var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink); // Act targetMock.Object.Visit(results); // Assert targetMock.Verify(v => v.OnComplete()); }
internal bool Merge(ErrorSink/*!*/ errors, FormalTypeParam/*!*/ other) { if (this.name != other.Name) { PhpType declaring_type = (PhpType)parameter.DeclaringMember; errors.Add(Errors.PartialDeclarationsDifferInTypeParameter, declaring_type.Declaration.SourceUnit, position, declaring_type.FullName); return false; } attributes.Merge(other.Attributes); return true; }
public void VisitSendsDocumentToVisitor() { // Arrange Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>(); var root = new BlockBuilder() { Type = BlockType.Comment }.Build(); var errorSink = new ErrorSink(); var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink); // Act targetMock.Object.Visit(results); // Assert targetMock.Verify(v => v.VisitBlock(root)); }
// Allows MVC a chance to override the TagHelperDescriptorResolutionContext protected virtual TagHelperDescriptorResolutionContext GetTagHelperDescriptorResolutionContext( IEnumerable<TagHelperDirectiveDescriptor> descriptors, ErrorSink errorSink) { if (descriptors == null) { throw new ArgumentNullException(nameof(descriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } return new TagHelperDescriptorResolutionContext(descriptors, errorSink); }
public void EvaluateData( TagHelperDescriptorProvider provider, string documentContent, MarkupBlock expectedOutput, IEnumerable<RazorError> expectedErrors) { var errorSink = new ErrorSink(); var results = ParseDocument(documentContent, errorSink); var rewritingContext = new RewritingContext(results.Document, errorSink); new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext); var rewritten = rewritingContext.SyntaxTree; var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex) .ToList(); EvaluateRazorErrors(actualErrors, expectedErrors.ToList()); EvaluateParseTree(rewritten, expectedOutput); }
/// <summary> /// Instantiates a new instance of <see cref="TagHelperDescriptorResolutionContext"/>. /// </summary> /// <param name="directiveDescriptors"><see cref="TagHelperDirectiveDescriptor"/>s used to resolve /// <see cref="TagHelperDescriptor"/>s.</param> /// <param name="errorSink">Used to aggregate <see cref="RazorError"/>s.</param> public TagHelperDescriptorResolutionContext( IEnumerable<TagHelperDirectiveDescriptor> directiveDescriptors, ErrorSink errorSink) { if (directiveDescriptors == null) { throw new ArgumentNullException(nameof(directiveDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } DirectiveDescriptors = new List<TagHelperDirectiveDescriptor>(directiveDescriptors); ErrorSink = errorSink; }
public void CreateDescriptors_WithPrefixes_ReturnsExpectedAttributeDescriptors( Type tagHelperType, IEnumerable<TagHelperAttributeDescriptor> expectedAttributeDescriptors, string[] expectedErrorMessages) { // Arrange var errorSink = new ErrorSink(); // Act var descriptors = TagHelperDescriptorFactory.CreateDescriptors( AssemblyName, GetTypeInfo(tagHelperType), designTime: false, errorSink: errorSink); // Assert var errors = errorSink.Errors.ToArray(); Assert.Equal(expectedErrorMessages.Length, errors.Length); for (var i = 0; i < errors.Length; i++) { Assert.Equal(0, errors[i].Length); Assert.Equal(SourceLocation.Zero, errors[i].Location); Assert.Equal(expectedErrorMessages[i], errors[i].Message, StringComparer.Ordinal); } var descriptor = Assert.Single(descriptors); #if DNXCORE50 // In CoreCLR type forwarding of System.Runtime types causes issues with comparing FullNames for generic types. // We'll work around this by sanitizing the type names so that the assembly qualification is removed. foreach (var attributeDescriptor in expectedAttributeDescriptors) { attributeDescriptor.TypeName = RuntimeTypeInfo.SanitizeFullName(attributeDescriptor.TypeName); } foreach (var attributeDescriptor in descriptor.Attributes) { attributeDescriptor.TypeName = RuntimeTypeInfo.SanitizeFullName(attributeDescriptor.TypeName); } #endif Assert.Equal( expectedAttributeDescriptors, descriptor.Attributes, TagHelperAttributeDescriptorComparer.Default); }
public TagHelperDirectiveSpanVisitor( ITagHelperDescriptorResolver descriptorResolver, ErrorSink errorSink) { if (descriptorResolver == null) { throw new ArgumentNullException(nameof(descriptorResolver)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } _descriptorResolver = descriptorResolver; _errorSink = errorSink; }
public ParserContext(ITextDocument source, ParserBase codeParser, ParserBase markupParser, ParserBase activeParser, ErrorSink errorSink) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (codeParser == null) { throw new ArgumentNullException(nameof(codeParser)); } if (markupParser == null) { throw new ArgumentNullException(nameof(markupParser)); } if (activeParser == null) { throw new ArgumentNullException(nameof(activeParser)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (activeParser != codeParser && activeParser != markupParser) { throw new ArgumentException(RazorResources.ActiveParser_Must_Be_Code_Or_Markup_Parser, nameof(activeParser)); } CaptureOwnerTask(); Source = new TextDocumentReader(source); CodeParser = codeParser; MarkupParser = markupParser; ActiveParser = activeParser; _errorSink = errorSink; }
/// <inheritdoc /> public IEnumerable<Type> Resolve( string name, SourceLocation documentLocation, ErrorSink errorSink) { if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (string.IsNullOrEmpty(name)) { var errorLength = name == null ? 1 : Math.Max(name.Length, 1); errorSink.OnError( documentLocation, Resources.TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull, errorLength); return Type.EmptyTypes; } var assemblyName = new AssemblyName(name); IEnumerable<TypeInfo> libraryTypes; try { libraryTypes = GetExportedTypes(assemblyName); } catch (Exception ex) { errorSink.OnError( documentLocation, Resources.FormatTagHelperTypeResolver_CannotResolveTagHelperAssembly( assemblyName.Name, ex.Message), name.Length); return Type.EmptyTypes; } return libraryTypes.Where(IsTagHelper).Select(t => t.AsType()); }
/// <summary> /// Instantiates a new <see cref="ParserResults"/> instance. /// </summary> /// <param name="document">The <see cref="Block"/> for the syntax tree.</param> /// <param name="tagHelperDescriptors"> /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document. /// </param> /// <param name="errorSink"> /// The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the /// current Razor document. /// </param> public ParserResults(Block document, IEnumerable<TagHelperDescriptor> tagHelperDescriptors, ErrorSink errorSink) : this(!errorSink.Errors.Any(), document, tagHelperDescriptors, errorSink) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (tagHelperDescriptors == null) { throw new ArgumentNullException(nameof(tagHelperDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } }
public void CreateDescriptors_BuildsDescriptorsFromSimpleTypes() { // Arrange var errorSink = new ErrorSink(); var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name; var expectedDescriptor = CreateTagHelperDescriptor("object", "System.Object", objectAssemblyName); var factory = new TagHelperDescriptorFactory(designTime: false); // Act var descriptors = factory.CreateDescriptors( objectAssemblyName, GetTypeInfo(typeof(object)), errorSink: errorSink); // Assert Assert.Empty(errorSink.Errors); var descriptor = Assert.Single(descriptors); Assert.Equal(expectedDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default); }
internal static object[]/*!!*/ ToStaticTypeRefs(List<TypeRef>/*!*/ typeRefs, ErrorSink errors, SourceUnit sourceUnit) { if (typeRefs == null || typeRefs.Count == 0) return ArrayUtils.EmptyObjects; object[] result = new object[typeRefs.Count]; for (int i = 0; i < typeRefs.Count; i++) { if ((result[i] = typeRefs[i].ToStaticTypeRef(errors, sourceUnit)) == null) { if (errors != null) errors.Add(Errors.GenericParameterMustBeType, sourceUnit, typeRefs[i].Span); result[i] = new PrimitiveTypeName(QualifiedName.Object); } } return result; }
public void RenderAttributeValue_RendersModelExpressionsCorrectly( string modelExpressionType, string propertyType, string expectedValue) { // Arrange var renderer = new MvcTagHelperAttributeValueCodeRenderer( new GeneratedTagHelperAttributeContext { ModelExpressionTypeName = modelExpressionType, CreateModelExpressionMethodName = "SomeMethod", ModelExpressionProviderPropertyName = "Provider", ViewDataPropertyName = "ViewData" }); var attributeDescriptor = new TagHelperAttributeDescriptor { Name = "MyAttribute", PropertyName = "SomeProperty", TypeName = propertyType, }; var writer = new CSharpCodeWriter(); var generatorContext = new ChunkGeneratorContext( host: null, className: string.Empty, rootNamespace: string.Empty, sourceFile: string.Empty, shouldGenerateLinePragmas: true); var errorSink = new ErrorSink(); var context = new CodeGeneratorContext(generatorContext, errorSink); // Act renderer.RenderAttributeValue(attributeDescriptor, writer, context, (codeWriter) => { codeWriter.Write("MyValue"); }, complexValue: false); // Assert Assert.Equal(expectedValue, writer.GenerateCode()); }
public void RemoteCompile(ref ErrorSink /*!*/ errorSink, CompilationParameters /*!*/ ps) { lock (buildMutex) // TODO: do we need thread-safety (if yes, there is a better way)? { //if (++buildCounter % 10 == 0) // TODO: is it possible to estimate size of memory allocated by the domain? //{ // // if a referenced assembly gets updated then we should reload the domain as well // AppDomain.Unload(remoteCompiler.Domain); // remoteCompiler = null; //} if (remoteCompiler != null) { AppDomain.Unload(remoteCompiler.Domain); } remoteCompiler = ApplicationCompiler.CreateRemoteCompiler(); remoteCompiler.RemoteCompile(ref errorSink, ps); } }
public void Resolve_ResolvesTagHelperDescriptors() { // Arrange var assemblyNameLookups = new Dictionary <string, IEnumerable <Type> > { { CustomTagHelperAssembly, new[] { typeof(CustomTagHelper) } } }; var descriptorResolver = new TestAssemblyTagHelperDescriptorResolver(assemblyNameLookups); var errorSink = new ErrorSink(); // Act var descriptors = descriptorResolver.Resolve(CustomTagHelperAssembly, errorSink); // Assert Assert.NotNull(descriptors); var descriptor = Assert.Single(descriptors); Assert.Equal(CustomTagHelperAssembly, descriptor.AssemblyName, StringComparer.Ordinal); Assert.Equal(CustomTagHelperDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default); Assert.Empty(errorSink.Errors); }
/// <inheritdoc /> protected override IEnumerable <TagHelperDescriptor> GetTagHelperDescriptors( Block documentRoot, ErrorSink errorSink) { if (documentRoot == null) { throw new ArgumentNullException(nameof(documentRoot)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } var visitor = new ViewImportsTagHelperDirectiveSpanVisitor( TagHelperDescriptorResolver, _viewImportsDirectiveDescriptors, errorSink); return(visitor.GetDescriptors(documentRoot)); }
private void ValidateParentAllowsPlainTag(Block tagBlock, ErrorSink errorSink) { var tagName = GetTagName(tagBlock); // Treat partial tags such as '</' which have no tag names as content. if (string.IsNullOrEmpty(tagName)) { Debug.Assert(tagBlock.Children.First() is Span); ValidateParentAllowsContent((Span)tagBlock.Children.First(), errorSink); return; } var currentTracker = _trackerStack.Count > 0 ? _trackerStack.Peek() : null; if (HasAllowedChildren() && !_currentTagHelperTracker.AllowedChildren.Contains(tagName, StringComparer.OrdinalIgnoreCase)) { OnAllowedChildrenTagError(_currentTagHelperTracker, tagName, tagBlock, errorSink); } }
protected virtual ParserResults RunParse(string document, Func <ParserBase, Action> parserActionSelector, bool designTimeParser, Func <ParserContext, ParserBase> parserSelector = null, ErrorSink errorSink = null) { parserSelector = parserSelector ?? (c => c.ActiveParser); errorSink = errorSink ?? new ErrorSink(); // Create the source ParserResults results = null; using (var reader = new SeekableTextReader(document)) { try { var codeParser = CreateCodeParser(); var markupParser = CreateMarkupParser(); var context = CreateParserContext(reader, codeParser, markupParser, errorSink); context.DesignTimeMode = designTimeParser; codeParser.Context = context; markupParser.Context = context; // Run the parser parserActionSelector(parserSelector(context))(); results = context.CompleteParse(); } finally { if (results != null && results.Document != null) { WriteTraceLine(string.Empty); WriteTraceLine("Actual Parse Tree:"); WriteNode(0, results.Document); } } } return(results); }
private static bool ValidateName( string name, bool targetingAttributes, ErrorSink errorSink) { if (!targetingAttributes && string.Equals( name, TagHelperDescriptorProvider.ElementCatchAllTarget, StringComparison.OrdinalIgnoreCase)) { // '*' as the entire name is OK in the HtmlTargetElement catch-all case. return(true); } else if (targetingAttributes && name.EndsWith( TagHelperDescriptorProvider.RequiredAttributeWildcardSuffix, StringComparison.OrdinalIgnoreCase)) { // A single '*' at the end of a required attribute is valid; everywhere else is invalid. Strip it from // the end so we can validate the rest of the name. name = name.Substring(0, name.Length - 1); } var targetName = targetingAttributes ? Resources.TagHelperDescriptorFactory_Attribute : Resources.TagHelperDescriptorFactory_Tag; var validName = TryValidateName( name, whitespaceError: Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName), characterErrorBuilder: (invalidCharacter) => Resources.FormatHtmlTargetElementAttribute_InvalidName( targetName.ToLower(), name, invalidCharacter), errorSink: errorSink); return(validName); }
public IEnumerable <Type> Resolve( string name, SourceLocation documentLocation, ErrorSink errorSink) { if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (string.IsNullOrEmpty(name)) { var errorLength = name == null ? 1 : Math.Max(name.Length, 1); errorSink.OnError( documentLocation, "Tag Helper Assembly Name Cannot Be Empty Or Null", errorLength); return(Type.EmptyTypes); } IEnumerable <TypeInfo> libraryTypes; try { libraryTypes = GetExportedTypes(name); } catch (Exception ex) { errorSink.OnError( documentLocation, $"Cannot Resolve Tag Helper Assembly: {name}, {ex.Message}", name.Length); return(Type.EmptyTypes); } return(libraryTypes.Select(a => a.AsType())); }
protected override int OnExecute() { int protocol; if (ProtocolOption.HasValue()) { var protocolOptionValue = ProtocolOption.Value(); if (!int.TryParse(protocolOptionValue, out protocol)) { ReportError( string.Format( CultureInfo.CurrentCulture, Resources.CouldNotParseProvidedProtocol, protocolOptionValue)); return(0); } } else { protocol = AssemblyTagHelperDescriptorResolver.DefaultProtocolVersion; } var descriptorResolver = CreateDescriptorResolver(); descriptorResolver.ProtocolVersion = protocol; var errorSink = new ErrorSink(); var resolvedDescriptors = new List <TagHelperDescriptor>(); for (var i = 0; i < AssemblyNamesArgument.Values.Count; i++) { var assemblyName = AssemblyNamesArgument.Values[i]; var descriptors = descriptorResolver.Resolve(assemblyName, errorSink); resolvedDescriptors.AddRange(descriptors); } ReportResults(resolvedDescriptors, errorSink.Errors); return(0); }
private void ValidateParentAllowsContent(Span child, ErrorSink errorSink) { if (HasAllowedChildren()) { var content = child.Content; if (!string.IsNullOrWhiteSpace(content)) { var trimmedStart = content.TrimStart(); var whitespace = content.Substring(0, content.Length - trimmedStart.Length); var errorStart = SourceLocation.Advance(child.Start, whitespace); var length = trimmedStart.TrimEnd().Length; var allowedChildren = _currentTagHelperTracker.AllowedChildren; var allowedChildrenString = string.Join(", ", allowedChildren); errorSink.OnError( errorStart, RazorResources.FormatTagHelperParseTreeRewriter_CannotHaveNonTagContent( _currentTagHelperTracker.TagName, allowedChildrenString), length); } } }
public void SimpleRecordTest() { var code = @" record Person = FirstName: String; "; var errorSink = new ErrorSink(); var result = new Lexer(errorSink).Lex(code).ToList(); var nodes = new Parser(result, errorSink).Parse().ToList(); var node = nodes[0]; var foo = (RecordNode)node; Assert.Single(nodes); Assert.Empty(errorSink.Errors); Assert.IsType <RecordNode>(node); Assert.Equal("Person", foo.Id); var firstNameField = foo.Fields[0]; Assert.Equal("FirstName", firstNameField.Id); Assert.Equal("String", firstNameField.Type.ToString()); }
public void RenderAttributeValue_RendersModelExpressionsCorrectly( string modelExpressionType, string propertyType, string expectedValue) { // Arrange var renderer = new MvcTagHelperAttributeValueCodeRenderer( new GeneratedTagHelperAttributeContext { ModelExpressionTypeName = modelExpressionType, CreateModelExpressionMethodName = "SomeMethod" }); var attributeDescriptor = new TagHelperAttributeDescriptor { Name = "MyAttribute", PropertyName = "SomeProperty", TypeName = propertyType, }; var writer = new CSharpCodeWriter(); var generatorContext = new ChunkGeneratorContext( host: null, className: string.Empty, rootNamespace: string.Empty, sourceFile: string.Empty, shouldGenerateLinePragmas: true); var errorSink = new ErrorSink(); var context = new CodeGeneratorContext(generatorContext, errorSink); // Act renderer.RenderAttributeValue(attributeDescriptor, writer, context, (codeWriter) => { codeWriter.Write("MyValue"); }, complexValue: false); // Assert Assert.Equal(expectedValue, writer.GenerateCode()); }
private static IEnumerable <string> GetAllowedChildren(Type type, ErrorSink errorSink) { var restrictChildrenAttribute = type.GetTypeInfo().GetCustomAttribute <RestrictChildrenAttribute>(inherit: false); if (restrictChildrenAttribute == null) { return(null); } var allowedChildren = restrictChildrenAttribute.ChildTags; var validAllowedChildren = GetValidAllowedChildren(allowedChildren, type.FullName, errorSink); if (validAllowedChildren.Any()) { return(validAllowedChildren); } else { // All allowed children were invalid, return null to indicate that any child is acceptable. return(null); } }
private TagHelperRequiredAttributeDescriptor ParsePlainSelector(ErrorSink errorSink) { var nameEndIndex = _requiredAttributes.IndexOfAny(InvalidPlainAttributeNameCharacters, _index); string attributeName; var nameComparison = TagHelperRequiredAttributeNameComparison.FullMatch; if (nameEndIndex == -1) { attributeName = _requiredAttributes.Substring(_index); _index = _requiredAttributes.Length; } else { attributeName = _requiredAttributes.Substring(_index, nameEndIndex - _index); _index = nameEndIndex; if (_requiredAttributes[nameEndIndex] == RequiredAttributeWildcardSuffix) { nameComparison = TagHelperRequiredAttributeNameComparison.PrefixMatch; // Move past wild card _index++; } } TagHelperRequiredAttributeDescriptor descriptor = null; if (ValidateName(attributeName, targetingAttributes: true, errorSink: errorSink)) { descriptor = new TagHelperRequiredAttributeDescriptor { Name = attributeName, NameComparison = nameComparison }; } return(descriptor); }
public new virtual void Error(int lookaheadIndex, string format, params object[] args) { int index = InputPosition + lookaheadIndex; SourcePos pos; if (SourceFile == null) { pos = new SourcePos(FileName, LineNumber, index - LineStartAt + 1); } else { pos = SourceFile.IndexToLine(index); } if (ErrorSink != null) { if (args != null) { ErrorSink.Write(Severity.Error, pos, format, args); } else { ErrorSink.Write(Severity.Error, pos, format); } } else { string msg; if (args != null) { msg = Localize.From(format, args); } else { msg = Localize.From(format); } throw new FormatException(pos + ": " + msg); } }
object ParseLiteral2(UString typeMarker, UString parsedText, bool isNumericLiteral) { if (SkipValueParsing) { return(null); } if (PreferCustomLiterals) { return(new CustomLiteral(parsedText.ToString(), (Symbol)typeMarker.ToString())); } else { string syntaxError; var result = ParseLiteral(typeMarker, parsedText, isNumericLiteral, out syntaxError); if (syntaxError != null) { var pos = new SourceRange(SourceFile, _startPosition, InputPosition - _startPosition); ErrorSink.Write(Severity.Error, pos, syntaxError); } return(result); } }
public bool Verify(Dafny.Program dafnyProgram, ResolverTagger resolver, string uniqueIdPrefix, string requestId, ErrorReporterDelegate er) { Dafny.Translator translator = new Dafny.Translator(dafnyProgram.reporter); var translatorFlags = new Dafny.Translator.TranslatorFlags() { InsertChecksums = true, UniqueIdPrefix = uniqueIdPrefix }; var boogiePrograms = Dafny.Translator.Translate(dafnyProgram, dafnyProgram.reporter, translatorFlags); var impls = boogiePrograms.SelectMany(p => p.Item2.Implementations); resolver.ReInitializeVerificationErrors(requestId, impls); bool success = false; var errorSink = new ErrorSink(this); foreach (var kv in boogiePrograms) { var boogieProgram = kv.Item2; // TODO(wuestholz): Maybe we should use a fixed program ID to limit the memory overhead due to the program cache in Boogie. PipelineOutcome oc = BoogiePipeline(boogieProgram, 1 < Dafny.DafnyOptions.Clo.VerifySnapshots ? uniqueIdPrefix : null, requestId, errorSink, er); switch (oc) { case PipelineOutcome.Done: case PipelineOutcome.VerificationCompleted: // TODO: This would be the place to proceed to compile the program, if desired success = true; break; case PipelineOutcome.FatalError: default: return(false); } } return(success); }
private string ParseCssValue(ErrorSink errorSink) { int valueStart; int valueEnd; if (At('\'') || At('"')) { var quote = Current; // Move past the quote _index++; valueStart = _index; valueEnd = _requiredAttributes.IndexOf(quote, _index); if (valueEnd == -1) { errorSink.OnError( SourceLocation.Zero, Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeMismatchedQuotes( _requiredAttributes, quote), length: 0); return(null); } _index = valueEnd + 1; } else { valueStart = _index; var valueEndIndex = _requiredAttributes.IndexOfAny(InvalidCssQuotelessValueCharacters, _index); valueEnd = valueEndIndex == -1 ? _requiredAttributes.Length : valueEndIndex; _index = valueEnd; } var value = _requiredAttributes.Substring(valueStart, valueEnd - valueStart); return(value); }
public void CreateDescriptors_CreatesDesignTimeDescriptorsWithOutputElementHint( Type tagHelperType, TagHelperDescriptor[] expectedDescriptors) { // Arrange var errorSink = new ErrorSink(); // Act var descriptors = TagHelperDescriptorFactory.CreateDescriptors( AssemblyName, GetTypeInfo(tagHelperType), designTime: true, errorSink: errorSink); // Assert Assert.Empty(errorSink.Errors); // We don't care about order. Mono returns reflected attributes differently so we need to ensure order // doesn't matter by sorting. descriptors = descriptors.OrderBy(descriptor => descriptor.TagName); Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default); }
public void TagHelperResolution(bool designTime) { var descriptorResolver = new TagHelperDescriptorResolver(designTime); var errorSink = new ErrorSink(); var addTagHelperDirective = new TagHelperDirectiveDescriptor { DirectiveText = "*, Microsoft.AspNetCore.Mvc.TagHelpers", DirectiveType = TagHelperDirectiveType.AddTagHelper, Location = SourceLocation.Zero }; var resolutionContext = new TagHelperDescriptorResolutionContext( new[] { addTagHelperDirective }, errorSink); IEnumerable <TagHelperDescriptor> descriptors; using (Collector.StartCollection()) { descriptors = descriptorResolver.Resolve(resolutionContext); } Assert.NotEmpty(descriptors); Assert.Empty(errorSink.Errors); }
public static SourceDocument Parse(string sourceCode) { var errorSink = new ErrorSink(); var lexer = new Lexer.Lexer(errorSink); var parser = new Parser(errorSink); var src = new SourceCode(sourceCode); var tokens = lexer.LexFile(src).ToArray(); if (errorSink.HasErrors) { errorSink.ConsolePrint(); return(null); } var sourceDoc = parser.ParseFile(src, tokens); if (errorSink.HasErrors) { errorSink.ConsolePrint(); return(null); } return(sourceDoc); }
public void CanInstatiateLexer() { var code = @" # Chapter One This is a Paragraph, here we can write all the documentation that we'll ever want. @ This is an annotation record Person = FirstName: String; Some extra documentation view MyView = Controller Model View @ An annotation @ Another annotation component Controller = @ The Title @ Of the Controller component Title: This is the Controller component Model component View "; var errorSink = new ErrorSink(); var result = new Lexer(errorSink).Lex(code).ToList(); Assert.NotNull(result); Assert.Equal(149, result.Count); }
public void Compile_ReturnsFailedResultIfParseFails() { // Arrange var errorSink = new ErrorSink(); errorSink.OnError(new RazorError("some message", 1, 1, 1, 1)); var generatorResult = new GeneratorResults( new Block(new BlockBuilder { Type = BlockType.Comment }), Enumerable.Empty<TagHelperDescriptor>(), errorSink, new CodeGeneratorResult("", new LineMapping[0]), new ChunkTree()); var host = new Mock<IMvcRazorHost>(); host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>())) .Returns(generatorResult) .Verifiable(); var fileInfo = new Mock<IFileInfo>(); fileInfo.Setup(f => f.CreateReadStream()) .Returns(Stream.Null); var compiler = new Mock<ICompilationService>(MockBehavior.Strict); var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml"); var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance); // Act var result = razorService.Compile(relativeFileInfo); // Assert Assert.NotNull(result.CompilationFailures); Assert.Collection(result.CompilationFailures, failure => { var message = Assert.Single(failure.Messages); Assert.Equal("some message", message.Message); }); host.Verify(); }
// This is all that's needed to run code on behalf of language-independent // DLR hosting. Sympl defines its own subtype of ScriptCode. // public override ScriptCode CompileSourceCode( SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink) { using (var reader = sourceUnit.GetReader()) { try { switch (sourceUnit.Kind) { case SourceCodeKind.SingleStatement: case SourceCodeKind.Expression: case SourceCodeKind.AutoDetect: case SourceCodeKind.InteractiveCode: return(new SymplScriptCode( _sympl, _sympl.ParseExprToLambda(reader), sourceUnit)); case SourceCodeKind.Statements: case SourceCodeKind.File: return(new SymplScriptCode( _sympl, _sympl.ParseFileToLambda(sourceUnit.Path, reader), sourceUnit)); default: throw Assert.Unreachable; } } catch (Exception e) { // Real language implementation would have a specific type // of exception. Also, they would pass errorSink down into // the parser and add messages while doing tighter error // recovery and continuing to parse. errorSink.Add(sourceUnit, e.Message, SourceSpan.None, 0, Severity.FatalError); return(null); } } }
internal override ComponentNode? Parse() { var keyWordComponent = Take(TokenType.KwComponent); var id = ParserIdentifier(); if (id is null) return null; var fields = new List<ArchitectureField>(); var equals = TakeWithoutSpace(TokenType.Equals); if (equals is null) return new ComponentNode(id, fields); while (_hasField()) { Take(TokenType.NewLine); Take(TokenType.Indent); var fieldId = Take(TokenType.Identifier); if (fieldId is null) { ErrorSink.AddError(Current ?? Token.Default, ErrorType.InvalidIdentifier, $"A field should have an Identifier."); continue; } TakeWithoutSpace(TokenType.Colon); var root = Take() ?? Token.Default; while (_stillInFieldDefinition()) { if (Current == TokenType.Indent) Take(); else root = root.Append(Take()); } fields.Add(new ArchitectureField(fieldId, root)); } return new ComponentNode(id, fields); }
private bool?Evaluate(LNode expr) { if (expr.IsId) { return(DefinedSymbols.Contains(expr.Name)); } else if (expr.IsLiteral && expr.Value is bool) { return((bool)expr.Value); } else if (expr.Calls(S.And, 2)) { return(Evaluate(expr.Args[0]) & Evaluate(expr.Args[1])); } else if (expr.Calls(S.Or, 2)) { return(Evaluate(expr.Args[0]) | Evaluate(expr.Args[1])); } else if (expr.Calls(S.Not, 1)) { return(!Evaluate(expr.Args[0])); } else if (expr.Calls(S.Eq, 2)) { return(Evaluate(expr.Args[0]) == Evaluate(expr.Args[1])); } else if (expr.Calls(S.Neq, 2)) { return(Evaluate(expr.Args[0]) != Evaluate(expr.Args[1])); } else { ErrorSink.Write(Severity.Error, expr.Range, "Only simple boolean expressions with &&, ||, !, ==, !=, are supported in #if and #elif"); return(null); } }
/// <summary> /// Creates a <see cref="TagHelperDescriptor"/> from the given <paramref name="typeInfo"/>. /// </summary> /// <param name="assemblyName">The assembly name that contains <paramref name="type"/>.</param> /// <param name="typeInfo">The <see cref="ITypeInfo"/> to create a <see cref="TagHelperDescriptor"/> from. /// </param> /// <param name="designTime">Indicates if the returned <see cref="TagHelperDescriptor"/>s should include /// design time specific information.</param> /// <param name="errorSink">The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered /// when creating <see cref="TagHelperDescriptor"/>s for the given <paramref name="typeInfo"/>.</param> /// <returns> /// A collection of <see cref="TagHelperDescriptor"/>s that describe the given <paramref name="typeInfo"/>. /// </returns> public static IEnumerable <TagHelperDescriptor> CreateDescriptors( string assemblyName, ITypeInfo typeInfo, bool designTime, ErrorSink errorSink) { if (typeInfo == null) { throw new ArgumentNullException(nameof(typeInfo)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (ShouldSkipDescriptorCreation(designTime, typeInfo)) { return(Enumerable.Empty <TagHelperDescriptor>()); } var attributeDescriptors = GetAttributeDescriptors(typeInfo, designTime, errorSink); var targetElementAttributes = GetValidHtmlTargetElementAttributes(typeInfo, errorSink); var allowedChildren = GetAllowedChildren(typeInfo, errorSink); var tagHelperDescriptors = BuildTagHelperDescriptors( typeInfo, assemblyName, attributeDescriptors, targetElementAttributes, allowedChildren, designTime); return(tagHelperDescriptors.Distinct(TagHelperDescriptorComparer.Default)); }
/// <summary> /// Loads an <see cref="Assembly"/> using the given <paramref name="name"/> and resolves /// all valid <see cref="ITagHelper"/> <see cref="Type"/>s. /// </summary> /// <param name="name">The name of an <see cref="Assembly"/> to search.</param> /// <param name="documentLocation">The <see cref="SourceLocation"/> of the associated /// <see cref="Parser.SyntaxTree.SyntaxTreeNode"/> responsible for the current <see cref="Resolve"/> call. /// </param> /// <param name="errorSink">The <see cref="ErrorSink"/> used to record errors found when resolving /// <see cref="ITagHelper"/> <see cref="Type"/>s.</param> /// <returns>An <see cref="IEnumerable{Type}"/> of valid <see cref="ITagHelper"/> <see cref="Type"/>s. /// </returns> public IEnumerable <Type> Resolve(string name, SourceLocation documentLocation, [NotNull] ErrorSink errorSink) { if (string.IsNullOrEmpty(name)) { errorSink.OnError(documentLocation, Resources.TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull); return(Type.EmptyTypes); } var assemblyName = new AssemblyName(name); IEnumerable <TypeInfo> libraryTypes; try { libraryTypes = GetExportedTypes(assemblyName); } catch (Exception ex) { errorSink.OnError( documentLocation, Resources.FormatTagHelperTypeResolver_CannotResolveTagHelperAssembly( assemblyName.Name, ex.Message)); return(Type.EmptyTypes); } var validTagHelpers = libraryTypes.Where(IsTagHelper); // Convert from TypeInfo[] to Type[] return(validTagHelpers.Select(type => type.AsType())); }
/// <summary> /// Instantiates a new <see cref="GeneratorResults"/> instance. /// </summary> /// <param name="document">The <see cref="Block"/> for the syntax tree.</param> /// <param name="tagHelperDescriptors"> /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document. /// </param> /// <param name="errorSink"> /// The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the /// current Razor document. /// </param> /// <param name="codeGeneratorResult">The results of generating code for the document.</param> /// <param name="chunkTree">A <see cref="ChunkTree"/> for the document.</param> public GeneratorResults(Block document, IEnumerable <TagHelperDescriptor> tagHelperDescriptors, ErrorSink errorSink, CodeGeneratorResult codeGeneratorResult, ChunkTree chunkTree) : base(document, tagHelperDescriptors, errorSink) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (tagHelperDescriptors == null) { throw new ArgumentNullException(nameof(tagHelperDescriptors)); } if (errorSink == null) { throw new ArgumentNullException(nameof(errorSink)); } if (codeGeneratorResult == null) { throw new ArgumentNullException(nameof(codeGeneratorResult)); } if (chunkTree == null) { throw new ArgumentNullException(nameof(chunkTree)); } GeneratedCode = codeGeneratorResult.Code; DesignTimeLineMappings = codeGeneratorResult.DesignTimeLineMappings; ChunkTree = chunkTree; }
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable <TagHelperDescriptor> descriptors) { var errorSink = new ErrorSink(); var rewriter = new Rewriter( syntaxTree.Source, tagHelperPrefix, descriptors, syntaxTree.Options.FeatureFlags, errorSink); var rewritten = rewriter.Visit(syntaxTree.Root); var errorList = new List <RazorDiagnostic>(); errorList.AddRange(errorSink.Errors); errorList.AddRange(descriptors.SelectMany(d => d.GetAllDiagnostics())); var diagnostics = CombineErrors(syntaxTree.Diagnostics, errorList).OrderBy(error => error.Span.AbsoluteIndex); var newSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, diagnostics, syntaxTree.Options); return(newSyntaxTree); }
private static bool EnsureValidPrefix( string prefix, SourceLocation directiveLocation, ErrorSink errorSink) { foreach (var character in prefix) { // Prefixes are correlated with tag names, tag names cannot have whitespace. if (char.IsWhiteSpace(character) || TagHelperDescriptorFactory.InvalidNonWhitespaceNameCharacters.Contains(character)) { errorSink.OnError( directiveLocation, Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperPrefixValue( SyntaxConstants.CSharp.TagHelperPrefixKeyword, character, prefix)); return(false); } } return(true); }
public void Resolve_CreatesErrors() { // Arrange var assemblyNameLookups = new Dictionary <string, IEnumerable <Type> > { { CustomTagHelperAssembly, new[] { typeof(InvalidTagHelper) } } }; var descriptorResolver = new TestAssemblyTagHelperDescriptorResolver(assemblyNameLookups); var errorSink = new ErrorSink(); // Act var descriptors = descriptorResolver.Resolve(CustomTagHelperAssembly, errorSink); // Assert Assert.NotEmpty(descriptors); var error = Assert.Single(errorSink.Errors); Assert.Equal( "Tag helpers cannot target tag name 'inv@lid' because it contains a '@' character.", error.Message, StringComparer.Ordinal); Assert.Equal(SourceLocation.Zero, error.Location); Assert.Equal(0, error.Length); }