sbt-proguard You have to specify '-keep' options for the shrinking step - sbt-proguard

I am struggling to get the sbt-proguard plugin to work. I have a class library that I want to obfuscate but I cannot seem to get the plugin to output without the above error. I have specified the keep option, or at lease I think that I have, but I have had no luck. I copied the keep options from the Proguard website which said it was meant for class libraries. In addition, I do not think the plug-in is responding the the options that I have configured.
For example, I wanted to have more verbose output to see if the output could give me a clue as to what I am doing wrong. However, whenever I look at the log files, it always specifies the default options. Below is my configuration. Can someone help me out with this one? I am completely lost. Thanks
import sbt.Keys._
import com.typesafe.sbt.SbtProguard._
import ProguardKeys._
lazy val commonDependencies = Seq(
Dependencies.Libraries.junit,
Dependencies.Libraries.springBootLogging,
Dependencies.Libraries.scalaMock,
Dependencies.Libraries.joda,
Dependencies.Libraries.scalaTestPlus,
Dependencies.Libraries.scalaXml,
Dependencies.Libraries.commonsCodec,
Dependencies.Libraries.typeSafeConfig
)
val keepClasses =
"""
|-injars in.jar
|-outjars out.jar
|-libraryjars <java.home>/lib/rt.jar
|-printmapping out.map
|
|-keepparameternames
|-renamesourcefileattribute SourceFile
|-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
| SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
|
|-keep public class * {
| public protected *;
|}
|
|-keepclassmembernames class * {
| java.lang.Class class$(java.lang.String);
| java.lang.Class class$(java.lang.String, boolean);
|}
|
|-keepclasseswithmembernames,includedescriptorclasses class * {
| native <methods>;
|}
|
|-keepclassmembers,allowoptimization enum * {
| public static **[] values();
| public static ** valueOf(java.lang.String);
|}
|
|-keepclassmembers class * implements java.io.Serializable {
| static final long serialVersionUID;
| private static final java.io.ObjectStreamField[] serialPersistentFields;
| private void writeObject(java.io.ObjectOutputStream);
| private void readObject(java.io.ObjectInputStream);
| java.lang.Object writeReplace();
| java.lang.Object readResolve();
|}
""".stripMargin
proguardSettings
lazy val skedaddleCore = (project in file(".")).
settings(BuildSettings.buildSettings: _*).
settings(
name := "core",
resolvers := Resolvers.all,
libraryDependencies ++= commonDependencies,
merge in Proguard := true,
proguardVersion in Proguard := "5.2.1",
options in Proguard --= Seq("-dontnote", "-dontwarn", "-ignorewarnings"),
options in Proguard ++= Seq("-verbose", "-dontshrink"),
options in Proguard += keepClasses
)

I finally got the plugin to do what I wanted with the following configuration.
import sbt.Keys._
import com.typesafe.sbt.SbtProguard._
lazy val commonDependencies = Seq(
Dependencies.Libraries.junit,
Dependencies.Libraries.springBootLogging,
Dependencies.Libraries.scalaMock,
Dependencies.Libraries.joda,
Dependencies.Libraries.scalaTestPlus,
Dependencies.Libraries.scalaXml,
Dependencies.Libraries.commonsCodec,
Dependencies.Libraries.typeSafeConfig
)
proguardSettings
ProguardKeys.proguardVersion in Proguard := "5.2.1"
ProguardKeys.options in Proguard ++= Seq("-dontnote", "-dontwarn", "-ignorewarnings")
ProguardKeys.inputs in Proguard <<= (dependencyClasspath in Compile) map { _.files }
ProguardKeys.filteredInputs in Proguard <++= (packageBin in Compile) map ProguardOptions.noFilter
val keepClasses =
"""
|-keepparameternames
|-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
| SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
|
|-keep,includedescriptorclasses interface com.** {
| <methods>;
|}
""".stripMargin
ProguardKeys.options in Proguard += keepClasses
lazy val skedaddleCore = (project in file(".")).
settings(BuildSettings.buildSettings: _*).
settings(
name := "core",
resolvers := Resolvers.all,
libraryDependencies ++= commonDependencies
)

Related

Why do lines 14 and 21 not compile (for my Kotlin function)?

I have a function named collectCustomizerFunctions which should create a MutableList<KCallable<*>> of all the functions of a specified class and its sub-classes which are annotated with CustomizerFunction.
Recursively, customizerFuns (the MutableList<KCallable<*>>) should have all of the "cutomizer functions" added to it.
When I try to build my Gradle project, it fails with two exceptions:
e: collectCustomizerFuns.kt:14:33 Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
e: collectCustomizerFuns.kt:21:30 Type mismatch: inferred type is Any but CapturedType(*) was expected
Here is my code:
3 | import kotlin.reflect.KClass
4 | import kotlin.reflect.KCallable
5 | import kotlin.reflect.full.allSuperclasses
6 |
7 | #Utility
8 | public tailrec fun <T: Any> collectCustomizerFuns(
9 | specClass: KClass<T>,
10 | customizerFuns: MutableList<KCallable<*>>
11 | ): Unit {
12 | // add annotated functions of this class
13 | for (member in specClass.members) {
14 | if (CustomizerFunction::class in member.annotations) { <--- ERROR
15 | customizerFuns.add(member)
16 | } else {}
17 | }
18 |
19 | // add annotated functions of all super-classes
20 | for (superclass in specClass.allSuperclasses) {
21 | collectCustomizerFuns<Any>(superclass, customizerFuns) <--- ERROR
22 | }
23 | }
I have been trying to fix these bugs for a while now, and would appreciate any help!
Also, please provide any constructive criticism you want regarding this function, it would help a lot!
For the first error, member.annotations returns List<Annotation>. You have to fetch actual classes of these annotations.
For the second error, remove the type where you call collectCustomizerFuns. Let kotlin infers the type by itself :).
So try this:
public tailrec fun <T: Any> collectCustomizerFuns(
specClass: KClass<T>,
customizerFuns: MutableList<KCallable<*>>
) {
// add annotated functions of this class
for (member in specClass.members) {
if (CustomizerFunction::class in member.annotations.map { it.annotationClass }) {
customizerFuns.add(member)
} else {
}
}
// add annotated functions of all super-classes
for (superclass in specClass.allSuperclasses ) {
collectCustomizerFuns(superclass, customizerFuns)
}
}
By the way, you can remove Unit from the method signature.

How do I use a module from multiple unit test modules?

I have two modules with unit tests and I want to access constants/variables with expected test results from both of those modules.
File: src/lib.rs
mod other;
#[cfg( test )]
mod tests {
mod expected;
use crate::tests::expected::FOUR;
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!( result, FOUR );
}
}
File: src/other.rs
#[cfg( test )]
mod tests {
use crate::tests::expected::EIGHT;
#[test]
fn it_works() {
let result = 4 + 4;
assert_eq!( result, EIGHT );
}
}
File src/tests/expected.rs
pub const FOUR: i32 = 4;
pub const EIGHT: i32 = 8;
From src/lib.rs I can access the constants within expected.rs. But this is not true from src/other.rs. I get the follwing error:
error[E0603]: module `expected` is private
--> src/other.rs:3:20
|
3 | use crate::tests::expected::EIGHT;
| ^^^^^^^^ private module
|
note: the module `expected` is defined here
--> src/lib.rs:5:2
|
5 | mod expected;
| ^^^^^^^^^^^^^
I have no idea how to make expected public. Where would I place expected.rs or how would I make it accessible from the test code of other modules of the library?

How to highlight an Xtext cross-reference differently for targets of different types?

I have an Xtext grammar which reads (in part):
grammar mm.ecxt.MMLanguage hidden(WS, COMMENT)
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
...
Statement:
ConstantStatement |
VariableStatement |
LabeledStatement |
...
LabeledStatement:
EssentialHypothesisStatement |
...
ConstantStatement:
DOLLAR_C (constants+=ConstDecl)+ DOLLAR_DOT;
VariableStatement:
DOLLAR_V (variables+=VarDecl)+ DOLLAR_DOT;
EssentialHypothesisStatement:
name=LABEL DOLLAR_E (symbols+=[Decl|MATHSYMBOL])+ DOLLAR_DOT;
Decl: ConstDecl | VarDecl;
ConstDecl returns ConstDecl: name=MATHSYMBOL;
VarDecl returns VarDecl: name=MATHSYMBOL;
MATHSYMBOL: PARENOPEN | PARENCLOSE | QUESTIONMARK | COMPRESSED | TLABEL | WORD;
...
(The full grammar is MMLanguage.xtext from current commit 328a5e7 of https://github.com/marnix/metamath-eclipse-xtext/.)
My question: How do I highlight the symbols in an EssentialHypothesisStatement, by using a different color for constants and variables? So if the MATHSYMBOL refers to a ConstDecl, then it should be highlighted one way, and some other way for a VarDecl.
I've tried to create an ISemanticHighlightingCalculator in all kinds of ways, but I can't seem to detect what the actual reference type is, neither through the node model nor through the Ecore model. On the one hand, the grammar-related methods only tell me that the reference goes to a Decl. On the other hand, the Ecore model's EReferences tell me whether the target is a ConstDecl or a VarDecl, but there I can't find the location of the source MATHSYMBOL.
Note that I prefer to use the node model (as opposed to the Ecore model) since I also want to highlight comments, and for performance reasons I cannot afford multiple passes over the document.
What is a good/canonical/efficient/simple way to achieve this?
from EObject perspective have a look at org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature(EObject, EStructuralFeature)
from the node model perspective you can use EObjectAtOffsetHelper
sample grammar
Model:
defs+=Def*
uses+=Use*
;
Def:
ADef | BDef;
ADef:
"adef" name=ID
;
BDef:
"bdef" name=ID
;
Use:
"use" def=[Def]
;
And here the Impl
public class MyDslSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
#Inject
private MyDslGrammarAccess ga;
#Inject
private EObjectAtOffsetHelper helper;
#Override
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor accoptor, CancelIndicator cancelIndicator) {
if (resource == null)
return;
IParseResult parseResult = resource.getParseResult();
if (parseResult == null || parseResult.getRootNode() == null)
return;
BidiTreeIterable<INode> tree = parseResult.getRootNode().getAsTreeIterable();
for (INode node : tree) {
if (cancelIndicator.isCanceled()) {
return;
}
if (node.getGrammarElement() instanceof CrossReference) {
if (ga.getUseAccess().getDefDefCrossReference_1_0() == node.getGrammarElement()) {
EObject target = helper.resolveElementAt(resource, node.getOffset());
if (target instanceof ADef) {
accoptor.addPosition(node.getOffset(), node.getLength(), HighlightingStyles.COMMENT_ID);
} else if (target instanceof BDef) {
accoptor.addPosition(node.getOffset(), node.getLength(), HighlightingStyles.STRING_ID);
}
}
}
}
}
}

Use trait from submodule with same name as struct

Trying to compile the following Rust code
mod traits {
pub trait Dog {
fn bark(&self) {
println!("Bow");
}
}
}
struct Dog;
impl traits::Dog for Dog {}
fn main() {
let dog = Dog;
dog.bark();
}
gives the error message
error[E0599]: no method named `bark` found for type `Dog` in the current scope
--> src/main.rs:15:9
|
9 | struct Dog;
| ----------- method `bark` not found for this
...
15 | dog.bark();
| ^^^^
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
1 | use crate::traits::Dog;
|
If I add use crate::traits::Dog;, the error becomes:
error[E0255]: the name `Dog` is defined multiple times
--> src/main.rs:11:1
|
1 | use crate::traits::Dog;
| ------------------ previous import of the trait `Dog` here
...
11 | struct Dog;
| ^^^^^^^^^^^ `Dog` redefined here
|
= note: `Dog` must be defined only once in the type namespace of this module
If I rename trait Dog to trait DogTrait, everything works. How can I use a trait from a submodule that has the same name as a struct in my main module?
You could rename the trait when importing it to get the same result without renaming the trait globally:
use traits::Dog as DogTrait;
The compiler now even suggests this:
help: you can use `as` to change the binding name of the import
|
1 | use crate::traits::Dog as OtherDog;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
documentation
If you don't wish to import both (or can't for whatever reason), you can use Fully Qualified Syntax (FQS) to use the trait's method directly:
fn main() {
let dog = Dog;
traits::Dog::bark(&dog);
}

SableCC not hitting interpreter methods

I am new to SableCC. Just ran the calculator example at http://sablecc.sourceforge.net/thesis/thesis.html#PAGE26. I used the grammar file and interpreter file as they are, and tried to parse simple arithmetic expression like "45 * 5 + 2". The problem is, the interpreter method caseAMultFactor does not seem to be hit. I see it hit caseAPlusExpr, or caseAMinusExpr if I change the "+" to "-". So does the Start.apply(DepthFirstAdapter) method only go through the top mode node? How can I iterate through all nodes like that sample codes seem to do? I am using Java 1.7 and hope that's not a problem.
For your convenience I have pasted the grammar and interpreter codes here. Thanks for your help.
### Grammar:
Package postfix;
Tokens
number = ['0' .. '9']+;
plus = '+';
minus = '-';
mult = '*';
div = '/';
mod = '%';
l_par = '(';
r_par = ')';
blank = (' ' | 13 | 10)+;
Ignored Tokens
blank;
Productions
expr =
{factor} factor |
{plus} expr plus factor |
{minus} expr minus factor;
factor =
{term} term |
{mult} factor mult term |
{div} factor div term |
{mod} factor mod term;
term =
{number} number |
{expr} l_par expr r_par;
### Interpreter:
package postfix.interpret;
import postfix.analysis.DepthFirstAdapter;
import postfix.node.ADivFactor;
import postfix.node.AMinusExpr;
import postfix.node.AModFactor;
import postfix.node.AMultFactor;
import postfix.node.APlusExpr;
import postfix.node.TNumber;
public class Interpreter extends DepthFirstAdapter
{
public void caseTNumber(TNumber node)
{// When we see a number, we print it.
System.out.print(node);
}
public void caseAPlusExpr(APlusExpr node)
{
System.out.println(node);
}
public void caseAMinusExpr(AMinusExpr node)
{
System.out.println(node);
}
public void caseAMultFactor(AMultFactor node)
{// out of alternative {mult} in Factor, we print the mult.
System.out.print(node.getMult());
}
public void outAMultFactor(AMultFactor node)
{// out of alternative {mult} in Factor, we print the mult.
System.out.print(node.getMult());
}
public void outADivFactor(ADivFactor node)
{// out of alternative {div} in Factor, we print the div.
System.out.print(node.getDiv());
}
public void outAModFactor(AModFactor node)
{// out of alternative {mod} in Factor, we print the mod.
System.out.print(node.getMod());
}
}
What you posted looks fine. You did not post any of the output, nor did you post the code to run the interpreter.
Here's my code (I'm omitting the code for Interpreter as it's the same as yours):
package postfix;
import postfix.parser.*;
import postfix.lexer.*;
import postfix.node.*;
import java.io.*;
public class Compiler {
public static void main(String[] arguments) {
try {
Parser p = new Parser(new Lexer(new PushbackReader(
new StringReader("(45 + 36/2) * 3 + 5 * 2"), 1024)));
Start tree = p.parse();
tree.apply(new Interpreter());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
and when run, it produces this:
45 36 2 / + 3 * 5 2 * +
Note the * is displayed, as expected.
UPDATE 2015-03-09
First, please copy/paste this grammar into a file named postfix.grammar. It should be the same as the one you have, but just copy/paste anyway:
Package postfix;
Tokens
number = ['0' .. '9']+;
plus = '+';
minus = '-';
mult = '*';
div = '/';
mod = '%';
l_par = '(';
r_par = ')';
blank = (' ' | 13 | 10)+;
Ignored Tokens
blank;
Productions
expr =
{factor} factor |
{plus} expr plus factor |
{minus} expr minus factor;
factor =
{term} term |
{mult} factor mult term |
{div} factor div term |
{mod} factor mod term;
term =
{number} number |
{expr} l_par expr r_par;
Next, run this from a command line (make any necessary directory changes, of course):
java -jar "C:\Program Files\Java\sablecc-3.2\lib\sablecc.jar" src\postfix.grammar
Please ensure that you only have the Java classes from this invocation of SableCC (i.e. make sure any previously generated Java classes are deleted). Then using the Compiler class that I previously posted, try again. I cannot think of any problem with the grammar or problem with version 3.2 of SableCC that would cause the problem you're having. I'm hoping a fresh start will fix the problem.