コード例 #1
0
        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);
        }
コード例 #2
0
        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}'");
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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));
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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));
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        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);
        }
コード例 #12
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.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);
        }
コード例 #13
0
        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));
        }
コード例 #14
0
        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));
        }
コード例 #15
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));
        }
コード例 #16
0
        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}'.");
        }
コード例 #17
0
        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));
        }
コード例 #18
0
        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));
        }
コード例 #19
0
        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}'.");
        }