private bool CheckRoutineProperties(PhpSyntaxTree syntaxTree, IEnumerable <SourceRoutineSymbol> userDeclaredRoutines, MatchCollection expectedRoutineProps) { var positionRoutineMap = new Dictionary <int, SourceRoutineSymbol>( from routine in userDeclaredRoutines let position = (routine.Syntax as FunctionDecl)?.ParametersSpan.End ?? (routine.Syntax as MethodDecl)?.ParametersSpan.End where position != null select new KeyValuePair <int, SourceRoutineSymbol>(position.Value, routine)); // Routine properties are voluntary; therefore, check only the specified ones bool isCorrect = true; foreach (Match match in expectedRoutineProps) { int expectedPos = match.Index; if (!positionRoutineMap.TryGetValue(expectedPos, out var routine)) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine($"Cannot get routine information for properties on {linePos.Line},{linePos.Character}"); isCorrect = false; continue; } int expectedVersion = int.Parse(match.Groups[1].Value); int actualVersion = routine.ControlFlowGraph.FlowContext.Version; if (expectedVersion != actualVersion) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine( $"Wrong final flow analysis version {actualVersion} instead of {expectedVersion} of the routine {routine.Name} on {linePos.Line},{linePos.Character}"); isCorrect = false; } } return(isCorrect); }
private bool CheckParameterProperties(PhpSyntaxTree syntaxTree, IEnumerable <SymbolsSelector.SymbolStat> symbolStats, MatchCollection expectedParamProps) { var positionParamMap = new Dictionary <int, SourceParameterSymbol>( from symbolStat in symbolStats let symbol = symbolStat.Symbol where symbol is SourceParameterSymbol select new KeyValuePair <int, SourceParameterSymbol>(symbolStat.Span.End, (SourceParameterSymbol)symbol)); bool isCorrect = true; foreach (Match match in expectedParamProps) { int expectedPos = match.Index; if (!positionParamMap.TryGetValue(expectedPos, out var param)) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine($"Cannot get parameter information for properties on {linePos.Line},{linePos.Character}"); isCorrect = false; continue; } bool expectedSkipPass = (int.Parse(match.Groups[1].Value) != 0); bool actualSkipPass = !param.CopyOnPass; if (expectedSkipPass != actualSkipPass) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine( $"Wrong value of SkipPass {actualSkipPass} instead of {expectedSkipPass} of the parameter {param.Name} in {param.Routine.Name} on {linePos.Line},{linePos.Character}"); isCorrect = false; } } return(isCorrect); }
private bool CheckTypes(PhpSyntaxTree syntaxTree, IEnumerable <SymbolsSelector.SymbolStat> symbolStats, MatchCollection expectedTypes) { var positionSymbolMap = new Dictionary <int, SymbolsSelector.SymbolStat>(); foreach (var stat in symbolStats) { positionSymbolMap.TryAdd(stat.Span.Start, stat); } // Type annotation is voluntary; therefore, check only the specified types bool isCorrect = true; foreach (Match match in expectedTypes) { // The text of symbol should start where the annotation ends int expectedPos = match.Index + match.Length; if (!positionSymbolMap.TryGetValue(expectedPos, out var symbolStat)) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine($"Cannot get type information for type annotation on {linePos.Line},{linePos.Character}"); isCorrect = false; continue; } // Obtain the type of the given symbol or expression string actualType = GetTypeString(symbolStat); if (string.IsNullOrEmpty(actualType)) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(symbolStat.Span.ToTextSpan())); _output.WriteLine($"Unable to get the type of the symbol on {linePos.Line},{linePos.Character}"); isCorrect = false; continue; } // Reorder expected types alphabetically string expectedType = string.Join("|", match.Groups[1].Value.Split('|').OrderBy(s => s)); // Report any problem if (actualType != expectedType) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(symbolStat.Span.ToTextSpan())); _output.WriteLine( $"Wrong type {actualType} instead of {expectedType} of the expression on {linePos.Line},{linePos.Character}"); isCorrect = false; } } return(isCorrect); }
private void ReportMissingDiagnostic(PhpSyntaxTree syntaxTree, Match expectedMatch) { string idExpected = expectedMatch.Groups[1].Value; var span = new TextSpan(expectedMatch.Index, 0); var position = GetLinePosition(syntaxTree.GetLineSpan(span)); _output.WriteLine($"Missing diagnostic {idExpected} on {position.Line},{position.Character}"); }
private bool CheckOperationProperties(PhpSyntaxTree syntaxTree, IEnumerable <IPhpOperation> interestingOps, MatchCollection expectedOpProps) { var copyPositionSet = new HashSet <int>( interestingOps .OfType <BoundCopyValue>() .Select(c => c.Expression.PhpSyntax.Span.End)); bool isCorrect = true; foreach (Match match in expectedOpProps) { bool expectedSkipCopy = (int.Parse(match.Groups[1].Value) != 0); bool actualSkipCopy = !copyPositionSet.Contains(match.Index); if (expectedSkipCopy != actualSkipCopy) { var linePos = GetLinePosition(syntaxTree.GetLineSpan(match.GetTextSpan())); _output.WriteLine( $"Wrong value of copy skipping {actualSkipCopy} instead of {expectedSkipCopy} of the expression on {linePos.Line},{linePos.Character}"); isCorrect = false; } } return(isCorrect); }