how to edit node using Analyser in dart - dart

How to edit a source file in dart using analyser.
This is what i tried
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
String src = """
Dynamism d = new Dynamism(expert:true);
main(){
var o = new Object();
d.on(o).hi = 'bye';
}
""";
main() {
var ast = parseCompilationUnit(src, parseFunctionBodies: true);
print('initial value: ');
print(ast.toSource());
var v = new Visitor();
ast.visitChildren(v);
print('After modification:');
print(ast.toSource());
}
class Visitor extends RecursiveAstVisitor {
#override
visitAssignmentExpression(AssignmentExpression node) {
//filter
var p = new RegExp(r'.*\.on\(\w\)');
if (!p.hasMatch(node.toString())) return;
//replace
SimpleStringLiteral ssl = _create_SimpleStringLiteral(node);
node.parent.accept(new NodeReplacer(node, ssl));
}
}
SimpleStringLiteral _create_SimpleStringLiteral(AstNode node) {
String new_string = modify(node.toString());
int line_num = node.offset;
//holds the position and type
StringToken st = new StringToken(TokenType.STRING, new_string,
line_num);
return new SimpleStringLiteral(st, new_string);
}
String modify(String s) {
List parts = s.split('=');
var value = parts[1];
List l = parts[0].split('.');
String dynamism = l.sublist(0, l.length - 1).join('.');
String propertyName = l.last.trim();
return '${dynamism}.set("${propertyName}",${value})';
}
but it's throwing error on SimpleStringLiteral, saying it is an Abstract Class. Please help me to edit 'bye' to 'goodbye'.i think previous version of dart has its implementation but now its abstract.

Instead of using
return new SimpleStringLiteral(st, new_string) try
return astFactory.simpleStringLiteral(st, new_string);
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
String src = """
Dynamism d = new Dynamism(expert:true);
main(){
var o = new Object();
d.on(o).hi = 'bye';
}
""";
main() {
var ast = parseCompilationUnit(src, parseFunctionBodies: true);
print('initial value: ');
print(ast.toSource());
var v = new Visitor();
ast.visitChildren(v);
print('After modification:');
print(ast.toSource());
}
class Visitor extends RecursiveAstVisitor {
#override
visitAssignmentExpression(AssignmentExpression node) {
//filter
var p = new RegExp(r'.*\.on\(\w\)');
if (!p.hasMatch(node.toString())) return;
//replace
SimpleStringLiteral ssl = _create_SimpleStringLiteral(node);
node.parent.accept(new NodeReplacer(node, ssl));
}
}
SimpleStringLiteral _create_SimpleStringLiteral(AstNode node) {
String new_string = modify(node.toString());
int line_num = node.offset;
//holds the position and type
StringToken st = new StringToken(TokenType.STRING, new_string,
line_num);
return astFactory.simpleStringLiteral(st, new_string);
}
String modify(String s) {
List parts = s.split('=');
var value = parts[1];
List l = parts[0].split('.');
String dynamism = l.sublist(0, l.length - 1).join('.');
String propertyName = l.last.trim();
return '${dynamism}.set("${propertyName}",${value})';
}

Related

how to get type of identifier dart-analyzer

I am processing method statements in a class and i want to find type of an identifier in those statements.
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:dstore/dstore.dart';
import 'package:dstore_generator/src/utils.dart';
import 'package:source_gen/source_gen.dart';
AstNode getAstNodeFromElement(Element element) {
AnalysisSession session = element.session;
ParsedLibraryResult parsedLibResult =
session.getParsedLibraryByElement(element.library);
ElementDeclarationResult elDeclarationResult =
parsedLibResult.getElementDeclaration(element);
return elDeclarationResult.node;
}
class SelectorsGenerator extends GeneratorForAnnotation<Selectors> {
#override
String generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
if (!(element is ClassElement)) {
throw Exception("Selectors should be applied on class only");
}
final className = element.name;
if (!className.startsWith("_")) {
throw Exception("Selectors functions class should start with _");
}
final modelName = className.substring(1);
final visitor = SelectorsVisitor(modelName);
final astNode = getAstNodeFromElement(element);
astNode.visitChildren(visitor);
return """
// Selector
""";
}
}
class SelectorsVisitor extends SimpleAstVisitor {
final String modelName;
final selectors = <String>[];
SelectorsVisitor(this.modelName);
#override
dynamic visitMethodDeclaration(MethodDeclaration node) {
final fields = convertParamsToFields(node.parameters);
if (fields.isEmpty || fields.length > 1) {
throw Exception(
"Selector functions should be only one param with app state");
}
final field = fields.first;
var name = node.name.toString();
if (node.returnType == null) {
throw Exception("You sould annontate return type of method ${name} ");
}
final rType = node.returnType.toString();
final sType = field.type;
final bvs = SelectorBodyVisitor(field.param!.identifier);
node.body.visitChildren(bvs);
// node.body.visitChildren(visitor)
return super.visitMethodDeclaration(node);
}
}
class SelectorBodyVisitor extends RecursiveAstVisitor {
final Identifier identifier;
final List<List<String>> depsList = [];
SelectorBodyVisitor(this.identifier);
List<String> getListOfPropAccess(PropertyAccess node) {
final result = <String>[];
final prop = node.propertyName.toString();
result.add(prop);
final target = node.target;
print("target type ${target.runtimeType}");
if (target is PropertyAccess) {
result.addAll(getListOfPropAccess(target));
} else if (target is PrefixedIdentifier) {
if (target.prefix.toString() == identifier.toString()) {
// I am trying to get identifier type here
print("IdentifierElement2 ${target.identifier.staticType}");
result.add(target.identifier.toString());
} else {
print("target is not identifier ${target.runtimeType} ${target}");
}
}
return result;
}
#override
dynamic visitPropertyAccess(PropertyAccess node) {
print("***&&& propsAccess ${node}");
final list = getListOfPropAccess(node);
final sa = node.toString().split(".").toList();
if (sa.length - 1 == list.length) {
// property access of state identifier
depsList.add(list.reversed.toList().take(2).toList());
}
print("Property access list ++++=== ++++++ ${list}");
}
#override
dynamic visitPrefixedIdentifier(PrefixedIdentifier node) {
print(
"**##### IdenAccess ${node} id: ${node.identifier} prefix : ${node.prefix} mid :${identifier.toString()}");
if (node.prefix.toString() == identifier.toString()) {
print("IdentifierElement1 ${node.identifier.staticType}");
depsList.add([node.identifier.toString()]);
} else {
print("identifier is not equal ${node.prefix == identifier}");
}
}
}
Example
class User {
final String name;
User(this.name)
}
class Model {
final User user;
Model(this.user)
}
#Selectors()
abstract class MySelectors {
static s1(Model model) {
final n = model.user.name; // i want to know type of name in code generation time , please check this line print("IdentifierElement2 ${target.identifier.staticType}"); in above code , where i am getting null
}
}
Found answer , I have to use getResolvedLibraryByElement instead of getParsedLibraryByElement in getAstNodeFromElement method.
Future<AstNode> getAstNodeFromElement(Element element) async {
AnalysisSession session = element.session;
final s = await session.getResolvedLibraryByElement(element.library);
final s2 = s.getElementDeclaration(element);
return s2.node;
}

Out of Memory error when implementing breadth first search algorithm

I got the following error:
[error][1] (E/DartVM (14988): Exhausted heap space, trying to allocate 536870928 bytes.
E/flutter (14988): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Out of Memory)
When trying to implement a breadth_first search algorithm to find the shortest path in a graph. I found the algorithm written in C# and I am trying to rewrite it in dart/flutter.
The original code in C# can be found here.
My dart code:
import 'dart:collection';
import 'package:stack/stack.dart';
class Node<T>{
int id;
Node(this.id);
String toString() => '$id';
}
class Graph<T>{
final Map<Node, List<Node>> adj;
Graph(this.adj);
void AddEdge(Node node1,Node node2){
if(!adj.containsKey(node1))
adj[node1]=List<Node>();
if(!adj.containsKey(node2))
adj[node2]=List<Node>();
adj[node1].add(node2);
adj[node2].add(node1);
}
Stack<Node> ShortestPath(Node source, Node dest){
var path=Map<Node<T>,Node<T>>();
var distance=Map<Node<T>,int>();
//adj.keys.forEach(( node) => distance[node]=-1);
for(var node in adj.keys){
distance[node]=-1;
}
distance[source]=0;
var q=Queue<Node<T>>();
q.add(source);
while(q.isNotEmpty){
var node=q.removeFirst();
for(var adjs in adj[node].where((n) => distance[n]==-1)){
distance[adjs]=distance[node]+1;
path[adjs]=node;
q.add(adjs);
}
}
var res=Stack<Node>();
var cur=dest;
while(cur != res){
res.push(cur);
cur=path[cur];
}
res.push(source);
return res;
}
}
void main() {
var g = new Graph({});
var n1 = new Node<int>(1);
var n2 = new Node<int>(2);
var n3 = new Node<int>(3);
var n4 = new Node<int>(4);
var n5 = new Node<int>(5);
var n6 = new Node<int>(6);
var n7 = new Node<int>(7);
g.AddEdge(n1, n2);
g.AddEdge(n1, n3);
g.AddEdge(n1, n4);
g.AddEdge(n4, n5);
g.AddEdge(n2, n6);
g.AddEdge(n4, n7);
g.AddEdge(n5, n6);
g.AddEdge(n6, n7);
var answ=g.ShortestPath(n1, n7);
print(answ);
}
So what is the wrong with my program, and if anyone know better way to find shortest path in graph to use it in dart it will be great.
Thanks in advance
First, you main problem is properly that your while loop is not correct according to the C# implementation:
var res=Stack<Node>();
var cur=dest;
while(cur != res){
res.push(cur);
cur=path[cur];
}
res.push(source);
return res;
This loop will never finish res and cur are entirely different types where cur are a Node and res are a Stack. If you check the C# implementation you can see this is not correct:
var res = new Stack<Node<T>>();
var cur = dest;
while(cur != source) {
res.Push(cur);
cur = path[cur];
}
res.Push(source);
return res;
So I think by comparing against source it will properly solve the problem. But there are a lot of smaller problems in you code where types are not really great and where you could make it a lot more type safe by using generics more places.
I have therefore added more typing information to you code (which I needed to do to catch the type error). I have also dropped the usage of the Stack class since I don't think it makes much sense. Also, the Stack class you got had no toString implementation so I just thought it was easier to just use a List and return that as the result:
import 'dart:collection';
class Node<T> {
int id;
Node(this.id);
#override
String toString() => '$id';
}
class Graph<T> {
final Map<Node<T>, List<Node<T>>> adj;
Graph(this.adj);
void AddEdge(Node<T> node1, Node<T> node2) {
if (!adj.containsKey(node1)) adj[node1] = <Node<T>>[];
if (!adj.containsKey(node2)) adj[node2] = <Node<T>>[];
adj[node1].add(node2);
adj[node2].add(node1);
}
List<Node<T>> ShortestPath(Node<T> source, Node<T> dest) {
final path = <Node<T>, Node<T>>{};
final distance = <Node<T>, int>{};
//adj.keys.forEach(( node) => distance[node]=-1);
for (final node in adj.keys) {
distance[node] = -1;
}
distance[source] = 0;
final q = Queue<Node<T>>();
q.add(source);
while (q.isNotEmpty) {
final node = q.removeFirst();
for (final adjs in adj[node].where((n) => distance[n] == -1)) {
distance[adjs] = distance[node] + 1;
path[adjs] = node;
q.add(adjs);
}
}
final res = <Node<T>>[];
var cur = dest;
while (cur != source) {
res.add(cur);
cur = path[cur];
}
res.add(source);
return res;
}
}
void main() {
final g = Graph<int>({});
final n1 = Node<int>(1);
final n2 = Node<int>(2);
final n3 = Node<int>(3);
final n4 = Node<int>(4);
final n5 = Node<int>(5);
final n6 = Node<int>(6);
final n7 = Node<int>(7);
g.AddEdge(n1, n2);
g.AddEdge(n1, n3);
g.AddEdge(n1, n4);
g.AddEdge(n4, n5);
g.AddEdge(n2, n6);
g.AddEdge(n4, n7);
g.AddEdge(n5, n6);
g.AddEdge(n6, n7);
final answ = g.ShortestPath(n1, n7);
print(answ); // [7, 4, 1]
}

How to extract date from tweets with lucene?

I have some tweets that I have already indexed "TweetIndexer" with lucene knowing that each tweet contains an ID, USER, TEXT, and DATE.
I want to only retrieve the date with another class "TweetSearcher" how to proceed?
Example of tweet:
"0","1467811372","Mon Apr 06 22:20:00 PDT 2009","NO_QUERY","joy_wolf","#Kwesidei not the whole crew ".
This my class TweetIndexer:
import org.apache.lucene.analysis.core.KeywordAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class TweetIndexer {
protected static final String COMMA = "\",\"";
protected static final String POLARITY = "polarity";
protected static final String ID = "id";
protected static final String DATE = "date";
protected static final String QUERY = "query";
protected static final String USER = "user";
protected static final String TEXT = "text";
public static void main(String[] args) throws Exception {
try {
String indexDir = "D:\\tweet\\index";
String dataFile = "D:\\tweet\\collection\\tweets.csv";
TweetIndexer tweetIndexer = new TweetIndexer();
long start = System.currentTimeMillis();
int count = tweetIndexer.index(new File(indexDir), new File(dataFile));
System.out.print(String.format("Indexed %d documents in %d seconds", count, (System.currentTimeMillis() - start) / 1000));
}
catch (Exception e) {
System.out.println("Usage: java TweetIndexer <index directory> <csv data file>");
}
}
private int index(File indexDir, File dataFile) throws Exception {
IndexWriter indexWriter = new IndexWriter(
FSDirectory.open(indexDir),
new IndexWriterConfig(Version.LUCENE_44, new KeywordAnalyzer()));
int count = indexFile(indexWriter, dataFile);
indexWriter.close();
return count;
}
private int indexFile(IndexWriter indexWriter, File dataFile) throws IOException {
FieldType fieldType = new FieldType();
fieldType.setStored(true);
fieldType.setIndexed(true);
BufferedReader bufferedReader = new BufferedReader(new FileReader(dataFile));
String line = "";
int count = 0;
while ((line = bufferedReader.readLine()) != null) {
// Hack to ignore commas within elements in csv (so we can split on "," rather than just ,)
line = line.substring(1, line.length() - 1);
String[] tweetInfo = line.split(COMMA);
Document document = new Document();
document.add(new Field(POLARITY, tweetInfo[0], fieldType));
document.add(new Field(ID, tweetInfo[1], fieldType));
document.add(new Field(DATE, tweetInfo[2], fieldType));
document.add(new Field(QUERY, tweetInfo[3], fieldType));
document.add(new StringField(USER, tweetInfo[4], Field.Store.YES));
document.add(new StringField(TEXT, tweetInfo[5], Field.Store.YES));
indexWriter.addDocument(document);
count++;
}
return count;
}
}
And this is short java code for my class TweetSearcher:
public class TweetSearcher {
public static void main(String[] args) throws Exception {
try {
String indexDir = "D:\\tweet\\index";
int numHits = Integer.parseInt("3");
TweetSearcher tweetSearcher = new TweetSearcher();
tweetSearcher.dateSearch(new File(indexDir), numHits);
private void dateSearch(File indexDir, int numHits) throws Exception {
System.out.println("Find dates:");
Directory directory = FSDirectory.open(indexDir);
DirectoryReader directoryReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(directoryReader);

How do I get all the fields of an object (including its superclass), using Dart's Mirrors API?

Given two Dart classes like:
class A {
String s;
int i;
bool b;
}
class B extends A {
double d;
}
And given an instance of B:
var b = new B();
How do I get all the fields in the b instance, including fields from its superclass?
Use dart:mirrors!
import 'dart:mirrors';
class A {
String s;
int i;
bool b;
}
class B extends A {
double d;
}
main() {
var b = new B();
// reflect on the instance
var instanceMirror = reflect(b);
var type = instanceMirror.type;
// type will be null for Object's superclass
while (type != null) {
// if you only care about public fields,
// check if d.isPrivate != true
print(type.declarations.values.where((d) => d is VariableMirror));
type = type.superclass;
}
}
import 'dart:mirrors';
class Test {
int a = 5;
static int s = 5;
final int _b = 6;
int get b => _b;
int get c => 0;
}
void main() {
Test t = new Test();
InstanceMirror instance_mirror = reflect(t);
var class_mirror = instance_mirror.type;
for (var v in class_mirror.declarations.values) {
var name = MirrorSystem.getName(v.simpleName);
if (v is VariableMirror) {
print("Variable: $name => S: ${v.isStatic}, P: ${v.isPrivate}, F: ${v.isFinal}, C: ${v.isConst}");
} else if (v is MethodMirror) {
print("Method: $name => S: ${v.isStatic}, P: ${v.isPrivate}, A: ${v.isAbstract}");
}
}
}

What can i do with a stored type?

Dart allows variables of types: Type type = SomeType; But for what purpose?
For example, foo bar baz are misapplications:
class A {
Type type = List;
foo() => new type();
type bar() {
return new List();
}
type baz = new List();
}
void main() {
Type type = String;
var str = "Hello Dart";
print(type == str.runtimeType);//true
print(str is String);//true
print(str is type); //type error.
}
I think this one is pretty neat:
void main() {
foo(Type t) {
switch (t){
case int: return 5;
case List: return [1,2,3]; // This one gets me every time :(
case String: return "Hello Dart!";
default: return "default";
}}
print(foo(10.runtimeType)); //5
print(foo([2,4,6].runtimeType)); //default
print(foo("lalala".runtimeType)); //Hello Dart!
print(foo(foo.runtimeType)); //default
}
Is its sole purpose to be the return type for methods like runtimeType and type matching ?
I don't think you can use it for generics. There you need type literals. But you can use it for reflection.
Just one simple example:
import 'dart:mirrors' as mirr;
class A {
String s;
A(this.s);
#override
String toString() => s;
}
void main() {
Type type = A;
var str = "Hello Dart";
mirr.ClassMirror cm = mirr.reflectType(type);
var s = cm.newInstance(new Symbol(''), [str]).reflectee;
print(s);
}
You could also create a Map with registered factories for different types to avoid the need for reflection.
(not tested)
class A {
String s;
int a = 0;
int b = 0;
int c = 0;
A(this.s);
A.extended(this.s, this.a, this.b, this.c);
#override
String toString() => '${super.toString()}: $s, $a, $b, $c';
}
void main(args) {
Type t = A;
registerType(t, (List args) => new A.extended(args[0], args[1], args[2], args[3]));
...
var a = getInstance(t, ['hallo', 1, 2, 3]);
}
Map<Type,Function> _factories = {};
void registerType(Type t, Function factory) {
_factories[t] = factory;
}
void getNewInstance(Type t, List args) {
return _factories[t](args);
}

Resources