public void TestIntrinsicFunctionOverloading(string function, string type1, string type2, string expectedMatchTypes) { var expressionCode = $"{function}(({type1}) 0, ({type2}) 0)"; var syntaxTree = SyntaxFactory.ParseExpression(expressionCode); var syntaxTreeSource = syntaxTree.Root.ToFullString(); Assert.Equal(expressionCode, syntaxTreeSource); var expression = (ExpressionSyntax)syntaxTree.Root; var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var combinedDiagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToList(); foreach (var d in combinedDiagnostics) { Debug.WriteLine(d); } var invokedFunctionSymbol = (FunctionSymbol)semanticModel.GetSymbol(expression); var diagnostic = combinedDiagnostics.SingleOrDefault(x => x.Severity == DiagnosticSeverity.Error); var result = diagnostic == null ? $"{invokedFunctionSymbol.Parameters[0].ValueType.ToMarkup()}, {invokedFunctionSymbol.Parameters[1].ValueType.ToMarkup()}" : ExpressionTestUtility.GetErrorString((DiagnosticId)diagnostic.Descriptor.Code); Assert.Equal(expectedMatchTypes, result); }
public void TestBinaryOperatorTypeConversions(string opText, string leftText, string rightText, string expectedResult) { var left = ExpressionTestUtility.GetValue(leftText); var right = ExpressionTestUtility.GetValue(rightText); var source = $"{left} {opText} {right}"; var syntaxTree = SyntaxFactory.ParseExpression(source); var syntaxTreeSource = syntaxTree.Root.ToString(); if (syntaxTreeSource != source) Assert.Fail($"Source should have been {syntaxTreeSource} but is {source}"); var expression = (BinaryExpressionSyntax)syntaxTree.Root; var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var leftType = ExpressionTestUtility.GetExpressionTypeString(semanticModel.GetExpressionType(expression.Left)); if (leftText != leftType) Assert.Fail($"Left should be of type '{leftText}' but has type '{leftType}'"); var rightType = ExpressionTestUtility.GetExpressionTypeString(semanticModel.GetExpressionType(expression.Right)); if (rightText != rightType) Assert.Fail($"Right should be of type '{rightText}' but has type '{rightType}'"); var diagnostic = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).SingleOrDefault(); var expressionType = semanticModel.GetExpressionType(expression); var result = diagnostic == null ? ExpressionTestUtility.GetExpressionTypeString(expressionType) : ExpressionTestUtility.GetErrorString(diagnostic.DiagnosticId); Assert.AreEqual(expectedResult, result, $"Expression {source} should have evaluated to '{expectedResult}' but was '{result}'"); }
public void SemanticModelForTypedef() { var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(@" typedef float2 Point; Point p;")); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); foreach (var diagnostic in semanticModel.GetDiagnostics()) { Debug.WriteLine(diagnostic); } Assert.Equal(0, semanticModel.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error)); var typedefStatement = (TypedefStatementSyntax)syntaxTree.Root.ChildNodes[0]; var variableDeclaration = (VariableDeclarationStatementSyntax)syntaxTree.Root.ChildNodes[1]; var typeAliasSymbol = semanticModel.GetDeclaredSymbol(typedefStatement.Declarators[0]); Assert.NotNull(typeAliasSymbol); Assert.Equal("Point", typeAliasSymbol.Name); var variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Declaration.Variables[0]); Assert.NotNull(variableSymbol); Assert.Equal("p", variableSymbol.Name); Assert.NotNull(variableSymbol.ValueType); Assert.Equal(typeAliasSymbol, variableSymbol.ValueType); }
public void TestBinaryOperatorTypeConversions(string opText, string leftText, string rightText, string expectedResult) { var left = ExpressionTestUtility.GetValue(leftText); var right = ExpressionTestUtility.GetValue(rightText); var source = $"{left} {opText} {right}"; var syntaxTree = SyntaxFactory.ParseExpression(source); var syntaxTreeSource = syntaxTree.Root.ToString(); Assert.Equal(source, syntaxTreeSource); var expression = (BinaryExpressionSyntax)syntaxTree.Root; var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var leftType = ExpressionTestUtility.GetExpressionTypeString(semanticModel.GetExpressionType(expression.Left)); Assert.Equal(leftText, leftType); var rightType = ExpressionTestUtility.GetExpressionTypeString(semanticModel.GetExpressionType(expression.Right)); Assert.Equal(rightText, rightType); var diagnostic = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).SingleOrDefault(); var expressionType = semanticModel.GetExpressionType(expression); var result = diagnostic == null ? ExpressionTestUtility.GetExpressionTypeString(expressionType) : ExpressionTestUtility.GetErrorString((DiagnosticId)diagnostic.Descriptor.Code); Assert.Equal(expectedResult, result); }
public void AllowsMissingFunctionImplementationIfUnused() { var code = @"void foo();"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.Empty(diagnostics); }
public void AllowsMissingFunctionImplementationIfUnused() { var code = @"void foo();"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.That(diagnostics, Is.Empty); }
public void DetectsRedefinitionAsFunction() { var code = @" struct foo {}; void foo();"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.That(diagnostics, Has.Length.EqualTo(1)); Assert.That(diagnostics[0].DiagnosticId, Is.EqualTo(DiagnosticId.SymbolRedefined)); }
public void DetectsFunctionRedefinition() { var code = @" void foo() {} void foo() {}"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.Equal(1, diagnostics.Length); Assert.Equal(DiagnosticId.SymbolRedefined, (DiagnosticId)diagnostics[0].Descriptor.Code); }
public void DetectsUndeclaredVariable() { var code = @" void main() { int foo = a; }"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.That(diagnostics, Has.Length.EqualTo(1)); Assert.That(diagnostics[0].DiagnosticId, Is.EqualTo(DiagnosticId.UndeclaredVariable)); }
public void DetectsUndeclaredVariable() { var code = @" void main() { int foo = a; }"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.Equal(1, diagnostics.Length); Assert.Equal(DiagnosticId.UndeclaredVariable, (DiagnosticId)diagnostics[0].Descriptor.Code); }
public void TestFunctionOverloadResolution2Args(string type1, string type2, string expectedMatchTypes) { var code = $@" int foo(int x, float y) {{ return 1; }} int foo(float x, float y) {{ return 2; }} int foo(double x, float y) {{ return 3; }} int foo(float x, int y) {{ return 4; }} int foo(float x, double y) {{ return 5; }} int foo(double x, int y) {{ return 6; }} int foo(int2 x, float y) {{ return 7; }} int foo(float2 x, float y) {{ return 8; }} int foo(double2 x, float y) {{ return 9; }} int foo(float3x3 x, float y) {{ return 10; }} void main() {{ foo({ExpressionTestUtility.GetValue(type1)}, {ExpressionTestUtility.GetValue(type2)}); }}"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var syntaxTreeSource = syntaxTree.Root.ToFullString(); Assert.Equal(code, syntaxTreeSource); var expression = (FunctionInvocationExpressionSyntax)syntaxTree.Root.ChildNodes .OfType <FunctionDefinitionSyntax>() .Where(x => x.Name.GetName() == "main") .Select(x => ((ExpressionStatementSyntax)x.Body.Statements[0]).Expression) .First(); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var combinedDiagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToList(); foreach (var d in combinedDiagnostics) { Debug.WriteLine(d); } var invokedFunctionSymbol = (FunctionSymbol)semanticModel.GetSymbol(expression); var diagnostic = combinedDiagnostics.SingleOrDefault(x => x.Severity == DiagnosticSeverity.Error); var result = diagnostic == null ? $"{invokedFunctionSymbol.Parameters[0].ValueType.ToMarkup()}, {invokedFunctionSymbol.Parameters[1].ValueType.ToMarkup()}" : ExpressionTestUtility.GetErrorString((DiagnosticId)diagnostic.Descriptor.Code); Assert.Equal(expectedMatchTypes, result); }
public void SemanticModelForStructAndFunction() { var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(@" struct MyStruct { float a; int b; }; void MyFunc() { MyStruct s; s.a = 1.0; }")); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var structDefinition = (TypeDeclarationStatementSyntax)syntaxTree.Root.ChildNodes[0]; var functionDefinition = (FunctionDefinitionSyntax)syntaxTree.Root.ChildNodes[1]; var variableDeclaration = (VariableDeclarationStatementSyntax)functionDefinition.Body.Statements[0]; var assignmentStatement = (ExpressionStatementSyntax)functionDefinition.Body.Statements[1]; var structSymbol = semanticModel.GetDeclaredSymbol((StructTypeSyntax)structDefinition.Type); Assert.NotNull(structSymbol); Assert.Equal("MyStruct", structSymbol.Name); Assert.Equal(2, structSymbol.Members.Length); var functionSymbol = semanticModel.GetDeclaredSymbol(functionDefinition); Assert.NotNull(functionSymbol); Assert.Equal("MyFunc", functionSymbol.Name); Assert.Equal(IntrinsicTypes.Void, functionSymbol.ReturnType); var variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Declaration.Variables[0]); Assert.NotNull(variableSymbol); Assert.Equal("s", variableSymbol.Name); Assert.NotNull(variableSymbol.ValueType); Assert.Equal(structSymbol, variableSymbol.ValueType); var assignmentExpressionType = semanticModel.GetExpressionType(assignmentStatement.Expression); Assert.NotNull(assignmentExpressionType); Assert.Equal(IntrinsicTypes.Float, assignmentExpressionType); }
public void DetectsMissingFunctionImplementation() { var code = @" void foo(); void main() { foo(); }"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var diagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToImmutableArray(); Assert.That(diagnostics, Has.Length.EqualTo(1)); Assert.That(diagnostics[0].DiagnosticId, Is.EqualTo(DiagnosticId.FunctionMissingImplementation)); }
public void CanGetSemanticModel(string testFile) { var sourceCode = File.ReadAllText(testFile); // Build syntax tree. var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(sourceCode), fileSystem: new TestFileSystem(testFile)); ShaderTestUtility.CheckForParseErrors(syntaxTree); // Get semantic model. var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); Assert.That(semanticModel, Is.Not.Null); foreach (var diagnostic in semanticModel.GetDiagnostics()) Debug.WriteLine(diagnostic); Assert.That(semanticModel.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error), Is.EqualTo(0)); }
public void SemanticModelForStructAndFunction() { var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(@" struct MyStruct { float a; int b; }; void MyFunc() { MyStruct s; s.a = 1.0; }")); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var structDefinition = (TypeDeclarationStatementSyntax) syntaxTree.Root.ChildNodes[0]; var functionDefinition = (FunctionDefinitionSyntax) syntaxTree.Root.ChildNodes[1]; var variableDeclaration = (VariableDeclarationStatementSyntax) functionDefinition.Body.Statements[0]; var assignmentStatement = (ExpressionStatementSyntax) functionDefinition.Body.Statements[1]; var structSymbol = semanticModel.GetDeclaredSymbol((StructTypeSyntax) structDefinition.Type); Assert.That(structSymbol, Is.Not.Null); Assert.That(structSymbol.Name, Is.EqualTo("MyStruct")); Assert.That(structSymbol.Members, Has.Length.EqualTo(2)); var functionSymbol = semanticModel.GetDeclaredSymbol(functionDefinition); Assert.That(functionSymbol, Is.Not.Null); Assert.That(functionSymbol.Name, Is.EqualTo("MyFunc")); Assert.That(functionSymbol.ReturnType, Is.EqualTo(IntrinsicTypes.Void)); var variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Declaration.Variables[0]); Assert.That(variableSymbol, Is.Not.Null); Assert.That(variableSymbol.Name, Is.EqualTo("s")); Assert.That(variableSymbol.ValueType, Is.Not.Null); Assert.That(variableSymbol.ValueType, Is.EqualTo(structSymbol)); var assignmentExpressionType = semanticModel.GetExpressionType(assignmentStatement.Expression); Assert.That(assignmentExpressionType, Is.Not.Null); Assert.That(assignmentExpressionType, Is.EqualTo(IntrinsicTypes.Float)); }
public void TestFunctionOverloadResolution1Arg(string type, string expectedMatchType) { var code = $@" struct MyStruct {{}}; int foo(int x) {{ return 1; }} int foo(float x) {{ return 2; }} int foo(double x) {{ return 3; }} int foo(int2 x) {{ return 4; }} int foo(float2 x) {{ return 5; }} int foo(double2 x) {{ return 6; }} int foo(float3x3 x) {{ return 7; }} void main() {{ foo(({type}) 0); }}"; var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(code)); var syntaxTreeSource = syntaxTree.Root.ToFullString(); Assert.AreEqual(code, syntaxTreeSource, $"Source should have been {code} but is {syntaxTreeSource}."); var expression = (FunctionInvocationExpressionSyntax) syntaxTree.Root.ChildNodes .OfType<FunctionDefinitionSyntax>() .Where(x => x.Name.GetName() == "main") .Select(x => ((ExpressionStatementSyntax) x.Body.Statements[0]).Expression) .First(); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var combinedDiagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToList(); foreach (var d in combinedDiagnostics) Debug.WriteLine(d); var invokedFunctionSymbol = (FunctionSymbol) semanticModel.GetSymbol(expression); var diagnostic = combinedDiagnostics.SingleOrDefault(x => x.Severity == DiagnosticSeverity.Error); var result = diagnostic == null ? ExpressionTestUtility.GetExpressionTypeString(invokedFunctionSymbol.Parameters[0].ValueType) : ExpressionTestUtility.GetErrorString(diagnostic.DiagnosticId); Assert.AreEqual(expectedMatchType, result, $"Expression should have matched the function overload '{expectedMatchType}' but it actually matched '{result}'."); }
public void CanGetSemanticModel(string testFile) { var sourceCode = File.ReadAllText(testFile); // Build syntax tree. var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(sourceCode, testFile), fileSystem: new TestFileSystem()); ShaderTestUtility.CheckForParseErrors(syntaxTree); // Get semantic model. var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); Assert.NotNull(semanticModel); foreach (var diagnostic in semanticModel.GetDiagnostics()) { Debug.WriteLine(diagnostic); } Assert.Equal(0, semanticModel.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error)); }
public void SemanticModelForTypedef() { var syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(@" typedef float2 Point; Point p;")); var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); foreach (var diagnostic in semanticModel.GetDiagnostics()) Debug.WriteLine(diagnostic); Assert.That(semanticModel.GetDiagnostics().Count(x => x.Severity == DiagnosticSeverity.Error), Is.EqualTo(0)); var typedefStatement = (TypedefStatementSyntax) syntaxTree.Root.ChildNodes[0]; var variableDeclaration = (VariableDeclarationStatementSyntax) syntaxTree.Root.ChildNodes[1]; var typeAliasSymbol = semanticModel.GetDeclaredSymbol(typedefStatement.Declarators[0]); Assert.That(typeAliasSymbol, Is.Not.Null); Assert.That(typeAliasSymbol.Name, Is.EqualTo("Point")); var variableSymbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Declaration.Variables[0]); Assert.That(variableSymbol, Is.Not.Null); Assert.That(variableSymbol.Name, Is.EqualTo("p")); Assert.That(variableSymbol.ValueType, Is.Not.Null); Assert.That(variableSymbol.ValueType, Is.EqualTo(typeAliasSymbol)); }
public void TestIntrinsicFunctionOverloading(string function, string type1, string type2, string expectedMatchTypes) { var expressionCode = $"{function}(({type1}) 0, ({type2}) 0)"; var syntaxTree = SyntaxFactory.ParseExpression(expressionCode); var syntaxTreeSource = syntaxTree.Root.ToFullString(); Assert.AreEqual(expressionCode, syntaxTreeSource, $"Source should have been {expressionCode} but is {syntaxTreeSource}."); var expression = (ExpressionSyntax) syntaxTree.Root; var compilation = new ShaderTools.Hlsl.Compilation.Compilation(syntaxTree); var semanticModel = compilation.GetSemanticModel(); var combinedDiagnostics = syntaxTree.GetDiagnostics().Concat(semanticModel.GetDiagnostics()).ToList(); foreach (var d in combinedDiagnostics) Debug.WriteLine(d); var invokedFunctionSymbol = (FunctionSymbol) semanticModel.GetSymbol(expression); var diagnostic = combinedDiagnostics.SingleOrDefault(x => x.Severity == DiagnosticSeverity.Error); var result = diagnostic == null ? $"{SymbolMarkup.ForSymbol(invokedFunctionSymbol.Parameters[0].ValueType)}, {SymbolMarkup.ForSymbol(invokedFunctionSymbol.Parameters[1].ValueType)}" : ExpressionTestUtility.GetErrorString(diagnostic.DiagnosticId); Assert.AreEqual(expectedMatchTypes, result, $"Expression should have matched the function overload '{expectedMatchTypes}' but it actually matched '{result}'."); }