diff --git a/.gitignore b/.gitignore index 6eca1307e..1c54f8f31 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ duplicates.txt /infer/tests/build_systems/incremental_analysis_cost_change/src /infer/tests/build_systems/incremental_analysis_add_procedure/src /infer/tests/build_systems/java_test_determinator/*.test +/infer/tests/build_systems/java_source_parser/*.test /_release /infer-source diff --git a/Makefile b/Makefile index 874825267..fec5c6b63 100644 --- a/Makefile +++ b/Makefile @@ -137,6 +137,7 @@ BUILD_SYSTEMS_TESTS += \ differential_skip_duplicated_types_on_filenames \ differential_skip_duplicated_types_on_filenames_with_renamings \ gradle \ + java_source_parser \ java_test_determinator \ javac \ resource_leak_exception_lines \ diff --git a/infer/src/java/jSourceFileInfo.mll b/infer/src/java/jSourceFileInfo.mll index 89fbf4ab2..4bbc6b708 100644 --- a/infer/src/java/jSourceFileInfo.mll +++ b/infer/src/java/jSourceFileInfo.mll @@ -402,7 +402,31 @@ and skip_comments action = parse In_channel.close cin ) - let debug_on_file _path = - (* TODO: do something here *) - () + let debug_on_file path = + if String.is_suffix path ~suffix:".java" then ( + let cin = In_channel.create path in + let stack = [] in + let record_location ~classname ~col ~line = + let cn : JBasics.class_name = JBasics.make_cn classname in + Printf.printf "class %s at line %d, column %d\n" + (JBasics.cn_name cn) line col in + try ( + let state = { record_location; stack; } in + class_scan state (from_channel cin) ; + In_channel.close cin ) + with + | Failure s -> + Printf.printf "Error parsing source file: %s" s; + In_channel.close cin + | Missing_opening_bracket -> + Printf.printf + "Missing opening bracket error while parsing source file\n"; + In_channel.close cin + | Missing_opening_parenthesis -> + Printf.printf + "Missing opening parenthesis error while parsing source file\n"; + In_channel.close cin + ) + + } diff --git a/infer/tests/build_systems/java_source_parser/ExampleCustomAnnotation.java b/infer/tests/build_systems/java_source_parser/ExampleCustomAnnotation.java new file mode 100644 index 000000000..e8378e79e --- /dev/null +++ b/infer/tests/build_systems/java_source_parser/ExampleCustomAnnotation.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +package java.source.parser; + +@interface ExampleCustomAnnotation { + String name(); + + String address(); +} diff --git a/infer/tests/build_systems/java_source_parser/Main.java b/infer/tests/build_systems/java_source_parser/Main.java new file mode 100644 index 000000000..7c1196ad6 --- /dev/null +++ b/infer/tests/build_systems/java_source_parser/Main.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +package java.source.parser; + +public class Main { + + // Tests for annotations + static interface Interface { + public Object foo(); + } + + @ExampleCustomAnnotation(name = "Chaitanya", address = "Agra, India") + class AnnotatedClass { + @Deprecated + void method1() { + return; + } + + @SuppressWarnings("deprecation") + void method2() { + return; + } + } + + static class Impl implements Interface { + @Override + public Object foo() { + return null; + } + } + + // tests for anonymous inner classes + static class MyThread { + MyThread(Object o) {} + + public static void main(String[] args) { + + Thread t1 = + new Thread() { + public void run() { + System.out.println("Child Thread"); + } + }; + t1.start(); + + Thread t2 = + new Thread( + new Runnable() { + public void run() { + System.out.println("Child Thread"); + } + }); + t2.start(); + + // nested anonymous classes + MyThread mt = + new MyThread( + new Object() { + private int counter; + + int get_counter() { + return this.counter; + } + }) { + private String label; + + String get_label() { + return this.label; + } + }; + } + } + + // tests for enum + + public enum Block { + NONE(""), + + WALL("Wall") { + @Override + public boolean good() { + return true; + } + }, + + PIT("Pit") { + @Override + public boolean good() { + return true; + } + }, + + FOG("Fog") { + @Override + public boolean good() { + return true; + } + }; + + private class C {}; + + private String name; + + private Block(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public boolean good() { + return false; + } + } +} diff --git a/infer/tests/build_systems/java_source_parser/Makefile b/infer/tests/build_systems/java_source_parser/Makefile new file mode 100644 index 000000000..c49f1d7de --- /dev/null +++ b/infer/tests/build_systems/java_source_parser/Makefile @@ -0,0 +1,28 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +TESTS_DIR = ../.. + +INFER_OPTIONS = --java-debug-source-file-info +SOURCES = Main.java + +test: parser.output.test + $(call check_no_diff,parser.output,parser.output.test) + +replace: parser.output.test + cp $< parser.output + +clean: + rm -fr infer-out parser.output.test *.class + +# we check if the java source file is valid for javac +compile: + javac *.java + +.PHONY: parser.output.test +parser.output.test: $(SOURCES) $(INFER_BIN) + $(INFER_BIN) $(INFER_OPTIONS) $(SOURCES) > parser.output.test + +include $(TESTS_DIR)/base.make diff --git a/infer/tests/build_systems/java_source_parser/parser.output b/infer/tests/build_systems/java_source_parser/parser.output new file mode 100644 index 000000000..6f688da9f --- /dev/null +++ b/infer/tests/build_systems/java_source_parser/parser.output @@ -0,0 +1,11 @@ +class java.source.parser.Main at line 9, column 13 +class java.source.parser.Main$Interface at line 12, column 19 +class java.source.parser.Main$AnnotatedClass at line 17, column 8 +class java.source.parser.Main$Impl at line 29, column 15 +class java.source.parser.Main$MyThread at line 37, column 15 +class java.source.parser.Main$MyThread$1 at line 43, column 23 +class java.source.parser.Main$MyThread$2 at line 52, column 29 +class java.source.parser.Main$MyThread$3 at line 62, column 27 +class java.source.parser.Main$MyThread$4 at line 68, column 17 +class java.source.parser.Main$Block at line 80, column 14 +class java.source.parser.Main$Block$C at line 104, column 18