public List <ImportStatement> Extract(RawCode code) { return(code.Lines .Select(line => line.Trim()) .SkipWhile(line => !line.StartsWith("using")) .TakeWhile((line, index) => line.StartsWith("using") && line.EndsWith(";")) .Select(line => new ImportStatement { Import = line, LineIndex = code.Lines.IndexOf(line) }) .ToList()); }
public void Process(string projectRootPath) { foreach (var entry in Directory.GetFiles(projectRootPath, "*.cs", SearchOption.AllDirectories)) { Console.WriteLine($"Processing {entry}"); var code = new RawCode { FilePath = entry, Lines = File.ReadAllLines(entry).ToList() }; // Replace content Replacer.Replace(code); // Overwrite existing content File.WriteAllLines(code.FilePath, code.Lines); } }
public void Replace(RawCode code) { var notImplementedEmitStrategy = new NotImplementedEmitStrategy(); var processed = new HashSet <string>(); MethodDefinition FindUnprocessed() { // We need to continuously extract methods if a modification changes indexing var definitions = MethodExtractor.ExtractMethods(code); return(definitions.FirstOrDefault(definition => !processed.Contains(definition.Signature))); } MethodDefinition next; while ((next = FindUnprocessed()) != default) { var bodyLineStart = next.MethodBody.LineStartIndex; var bodyLineEnd = next.MethodBody.LineEndIndex; switch (next.Declaration.Variant) { case MethodVariant.FullMethod: if (next.MethodBody.NumLines == 0) { continue; } var lines = new List <string>(next.MethodBody.NumLines); for (var i = 0; i < next.MethodBody.NumLines; i++) { lines.Add(EmitStrategy.Emit); } lines[^ 1] = notImplementedEmitStrategy.Emit;
public MethodDeclaration TryFind(int lineIndex, RawCode code) { var currLine = code.Lines[lineIndex].Trim(); if (string.IsNullOrEmpty(currLine)) { return(null); } // Ensure method begins with access modifier var parts = currLine.Split(" "); if (!AccessModifiers.Contains(parts[0]) && !Primitives.Contains(parts[0])) { return(null); } // Check inline format `int x(int y) => y * 2;` if (currLine.Contains("=>") && currLine.Contains(";") && !currLine.Contains("{") && !currLine.Contains("}")) { return(new MethodDeclaration { Signature = new CodeSegment { LineStartIndex = lineIndex, LineEndIndex = lineIndex, Content = currLine.Split("=>")[0].Trim() }, Variant = MethodVariant.InlineMethod }); } // Ensure we aren't looking at a class if (parts.Any(p => ClassTypes.Contains(p)) || parts.Length < 2) { return(null); } // We are looking at [accessModifier] [name] var numOpenParenthesis = currLine.Count(c => c == '('); var endIndex = -1; if (numOpenParenthesis > 0) { for (var i = lineIndex; i < code.Lines.Count; i++) { var numCloseParenthesis = code.Lines[i].Count(ch => ch == ')'); if (numCloseParenthesis > 0) { numOpenParenthesis -= numCloseParenthesis; } if (numOpenParenthesis == 0) { endIndex = i; break; } } } if (endIndex == -1 || !code.Lines[endIndex + 1].EndsWith("{")) { return(null); } var content = code.Join(lineIndex, endIndex); return(new MethodDeclaration { Variant = MethodVariant.FullMethod, Signature = new CodeSegment { Content = content, LineStartIndex = lineIndex, LineEndIndex = endIndex } }); }
public IEnumerable <string> ExtractDependencies(RawCode code) { return(code.Lines.TakeWhile(line => line.StartsWith("using"))); }
public IEnumerable <MethodDefinition> ExtractMethods(RawCode code) { var numOpenBrackets = 0; MethodDefinition currMethodDef = null; for (var i = 0; i < code.Lines.Count; i++) { var currLine = code.Lines[i].Trim(); if (currMethodDef == null) { var declaration = MethodDeclarationIdentifier.TryFind(i, code); if (declaration == null) { continue; } // Found new method definition var signatureLineEndIndex = declaration.Signature.LineEndIndex; var methodBody = declaration.Variant == MethodVariant.FullMethod ? new CodeSegment { LineStartIndex = signatureLineEndIndex + 2, LineEndIndex = signatureLineEndIndex + 1 } : new CodeSegment { LineStartIndex = signatureLineEndIndex, LineEndIndex = signatureLineEndIndex }; currMethodDef = new MethodDefinition { Signature = currLine, FullMethod = new CodeSegment { LineStartIndex = i, LineEndIndex = i }, MethodBody = methodBody, Declaration = declaration }; if (declaration.Variant == MethodVariant.InlineMethod) { currMethodDef.MethodBody.LineStartIndex = currMethodDef.MethodBody.LineEndIndex; currMethodDef.FullMethod.Content = currLine; currMethodDef.MethodBody.Content = currLine.Split("=>")[1].Trim(); yield return(currMethodDef); currMethodDef = null; } } else { // Check if } was reached, potentially end of method if (currLine.Contains("}")) { numOpenBrackets--; } if (currLine.Contains("{")) { numOpenBrackets++; } currMethodDef.FullMethod.LineEndIndex++; if (numOpenBrackets > 0) { // Expand method body length if an orphan { still exists currMethodDef.MethodBody.LineEndIndex++; } else { // Set full method content from line start to line end currMethodDef.FullMethod.Content = code.Join(currMethodDef.FullMethod); // Set method body content if (currMethodDef.MethodBody.NumLines == 0) { currMethodDef.MethodBody.Content = string.Empty; } else { currMethodDef.MethodBody.Content = code.Join(currMethodDef.MethodBody); if (currMethodDef.MethodBody.Content.Trim().Equals("}")) { currMethodDef.MethodBody.Content = string.Empty; } } yield return(currMethodDef); i = currMethodDef.FullMethod.LineEndIndex; // Reset method definition currMethodDef = null; } } } }