Skip to content

Commit

Permalink
SourceCode: 1. line location base api
Browse files Browse the repository at this point in the history
  • Loading branch information
chen56 committed Apr 20, 2024
1 parent 1a6c09e commit 9fa8eab
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 21 deletions.
2 changes: 1 addition & 1 deletion bake
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ get() { _run_all_package install; }
build() { _run_all_package build; }
upgrade() { _run_all_package upgrade;}
clean() { _run_all_package clean; }
tests() { _run_all_package test; }
test() { _run_all_package test; }
gen() { _run_all_package gen; }
ls(){
for pkg in ${!_pkgs[*]} ; do
Expand Down
105 changes: 105 additions & 0 deletions packages/you_note_dart/lib/src/content/source_code.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

import 'dart:io';

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';

class SourceCode {
final String content;
final CodeBlock? _build;

SourceCode._(this._build, this.content);

static SourceCode parseFile(String path) {
return SourceCode.parse(File(path).readAsStringSync());
}

static SourceCode parse(String content) {
var parseResult = parseString(content: content, featureSet: FeatureSet.latestLanguageVersion());
var unit = parseResult.unit;
_CodeVisitor visitor = _CodeVisitor(content);
unit.visitChildren(visitor);
return SourceCode._(visitor.build, content);
}

List<CodeBlock> get codesInBuild => _build == null
? []
: _build._children.isEmpty
? [_build]
: _build.children;

CodeBlock? findCellCode({required int line}) {
int offset = 0;
for (var MapEntry(key: i, value: lineContent) in content.split("\n").asMap().entries) {
if (i + 1 == line) {
break;
}
// '+1' : '\n'
offset += 1 + lineContent.length;
}

for (var code in codesInBuild) {
if (code.contains(offset)) {
return code;
}
}
return null;
}

line(int line) {
var lines = content.split("\n");
return lines[line - 1];
}
}

class CodeBlock {
final String content;
final int offset;
final int end;
final List<CodeBlock> _children = [];

CodeBlock({required this.offset, required this.end, required this.content});

int get length => end - offset;

List<CodeBlock> get children => List.unmodifiable(_children);

String get blockContent {
return content.substring(offset, end);
}

bool contains(int anOffset) {
return offset <= anOffset && anOffset <= end;
}

@override
String toString() {
return "$offset:$end";
}
}

class _CodeVisitor extends GeneralizingAstVisitor {
CodeBlock? build;
final String source;

_CodeVisitor(this.source);

@override
visitFunctionDeclaration(FunctionDeclaration node) {
if (node.name.lexeme == "build") {
var body = node.functionExpression.body as BlockFunctionBody;
var block = body.block;
build = CodeBlock(content: source, offset: block.leftBracket.end, end: block.rightBracket.offset);
}
return super.visitFunctionDeclaration(node);
}

@override
visitExpressionStatement(ExpressionStatement node) {
// FIXME go back
var expr = node.expression;
return super.visitExpressionStatement(node);
}
}
2 changes: 1 addition & 1 deletion packages/you_note_dart/lib/src/note_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ class Pen {
currentCell.print(object);
}

/// 注意:只能在NotePage的[build]函数的最外层调用,不能放在button回调或Timer回调中
/// 注意:只能在NotePage的[_build]函数的最外层调用,不能放在button回调或Timer回调中
/// 通过闭包记住currentCell的引用,以便可以在之后的回调中也可以print内容到currentCell
@experimental
@Deprecated("已经有更好的方案,这个废弃")
Expand Down
28 changes: 11 additions & 17 deletions packages/you_note_dart/test/code_analyzer/code_block_test.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import 'dart:io';

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:checks/checks.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:you_note_dart/src/content/source_code.dart';

void main() {
group("code analyzer", () {
test("block", () async {//packages/you_note_dart/lib/src/note_core.dart
File file=File.fromUri(Uri.file("test/code_analyzer/use_case_basic.dart"));
var parseResult = parseString(content: file.readAsStringSync(), featureSet: FeatureSet.latestLanguageVersion());
var unit = parseResult.unit;
unit.visitChildren(CodeVisitor());
test("block", () async {
SourceCode code = SourceCode.parseFile("test/code_analyzer/use_case_basic.dart");
check(code.line(8)).equals(r' print("x:$x");');
check(code.findCellCode(line: 8)!.blockContent).equals(r"""
// begin comment 中文字符
print("x:$x");
// end comment 中文字符
""");
});
});
}

class CodeVisitor extends GeneralizingAstVisitor{
@override
visitFunctionDeclaration(FunctionDeclaration node) {
return super.visitFunctionDeclaration(node);
}
}
7 changes: 5 additions & 2 deletions packages/you_note_dart/test/code_analyzer/use_case_basic.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'package:flutter/widgets.dart';
import 'package:you_note_dart/src/note_core.dart';

var x = "x";

void build(BuildContext context) {
debugPrint("x:$x");
void build(BuildContext context, Pen print) {
// begin comment 中文字符
print("x:$x");
// end comment 中文字符
}

class A {}

0 comments on commit 9fa8eab

Please sign in to comment.