reactor-core/src/main/java/reactor/core/publisher/Traces.java
static String extractOperatorAssemblyInformation(String source, boolean skipFirst) {
		String[] uncleanTraces = source.split("\n");
		final List<String> traces = Stream.of(uncleanTraces)
		                                  .map(String::trim)
		                                  .filter(s -> !s.isEmpty())
		                                  .skip(skipFirst ? 1 : 0)
		                                  .collect(Collectors.toList());

		if (traces.isEmpty()) {
			return "[no operator assembly information]";
		}

		int i = 0;
		while (i < traces.size() && !isUserCode(traces.get(i))) {
			i++;
		}

		String apiLine;
		String userCodeLine;
		if (i == 0) {
			//no line was a reactor API line
			apiLine = "";
			userCodeLine = traces.get(0);
		}
		else if (i == traces.size()) {
			//we skipped ALL lines, meaning they're all reactor API lines. We'll fully display the last one
			apiLine = "";
			userCodeLine = traces.get(i-1).replaceFirst("reactor.core.publisher.", "");
		}
		else {
			//currently on user code line, previous one is API
			apiLine = traces.get(i - 1);
			userCodeLine = traces.get(i);
		}

		//now we want something in the form "Flux.map ⇢ user.code.Class.method(Class.java:123)"
		if (apiLine.isEmpty()) return userCodeLine;

		int linePartIndex = apiLine.indexOf('(');
		if (linePartIndex > 0) {
			apiLine = apiLine.substring(0, linePartIndex);
		}
		apiLine = apiLine.replaceFirst("reactor.core.publisher.", "");

		return apiLine + " ⇢ " + userCodeLine;
	}
static String extractOperatorAssemblyInformation(String source, boolean skipFirst) {
		String[] uncleanTraces = source.split("\n");
		final List<String> traces = Stream.of(uncleanTraces)
		                                  .map(String::trim)
		                                  .filter(s -> !s.isEmpty())
		                                  .skip(skipFirst ? 1 : 0)
		                                  .collect(Collectors.toList());

		if (traces.isEmpty()) {
			return "[no operator assembly information]";
		}

		int i = 0;
		while (i < traces.size() && !isUserCode(traces.get(i))) {
			i++;
		}

		String apiLine;
		String userCodeLine;
		if (i == 0) {
			//no line was a reactor API line
			apiLine = "";
			userCodeLine = traces.get(0);
		}
		else if (i == traces.size()) {
			//we skipped ALL lines, meaning they're all reactor API lines. We'll fully display the last one
			apiLine = "";
			userCodeLine = traces.get(i-1).replaceFirst("reactor.core.publisher.", "");
		}
		else {
			//currently on user code line, previous one is API
			apiLine = traces.get(i - 1);
			userCodeLine = traces.get(i);
		}

		//now we want something in the form "Flux.map ⇢ user.code.Class.method(Class.java:123)"
		if (apiLine.isEmpty()) return userCodeLine;

		int linePartIndex = apiLine.indexOf('(');
		if (linePartIndex > 0) {
			apiLine = apiLine.substring(0, linePartIndex);
		}
		apiLine = apiLine.replaceFirst("reactor.core.publisher.", "");

		return apiLine + " ⇢ " + userCodeLine;
	}
static String extractOperatorAssemblyInformation ( String source , boolean skipFirst ) { String [ ] uncleanTraces = source . split ( "\n" ) ; final List < String > traces = Stream . of ( uncleanTraces ) . map ( String :: trim ) . filter ( s -> ! s . isEmpty ( ) ) . skip ( skipFirst ? 1 : 0 ) . collect ( Collectors . toList ( ) ) ; if ( traces . isEmpty ( ) ) { return "[no operator assembly information]" ; } int i = 0 ; while ( i < traces . size ( ) && ! isUserCode ( traces . get ( i ) ) ) { i ++ ; } String apiLine ; String userCodeLine ; if ( i == 0 ) { //no line was a reactor API line apiLine = "" ; userCodeLine = traces . get ( 0 ) ; } else if ( i == traces . size ( ) ) { //we skipped ALL lines, meaning they're all reactor API lines. We'll fully display the last one apiLine = "" ; userCodeLine = traces . get ( i - 1 ) . replaceFirst ( "reactor.core.publisher." , "" ) ; } else { //currently on user code line, previous one is API apiLine = traces . get ( i - 1 ) ; userCodeLine = traces . get ( i ) ; } //now we want something in the form "Flux.map ⇢ user.code.Class.method(Class.java:123)" if ( apiLine . isEmpty ( ) ) return userCodeLine ; int linePartIndex = apiLine . indexOf ( ' ' ) ; if ( linePartIndex > 0 ) { apiLine = apiLine . substring ( 0 , linePartIndex ) ; } apiLine = apiLine . replaceFirst ( "reactor.core.publisher." , "" ) ; return apiLine + " ⇢ " + u erCodeLine; }
Extract operator information out of an assembly stack trace in {@link String} form
(see {@link Traces#callSiteSupplierFactory}) which potentially
has a header line that one can skip by setting {@code skipFirst} to {@code true}.
<p>
Most operators will result in a line of the form {@code "Flux.map ⇢ user.code.Class.method(Class.java:123)"},
that is:
<ol>
<li>The top of the stack is inspected for Reactor API references, and the deepest
one is kept, since multiple API references generally denote an alias operator.
(eg. {@code "Flux.map"})</li>
<li>The next stacktrace element is considered user code and is appended to the
result with a {@code ⇢} separator. (eg. {@code " ⇢ user.code.Class.method(Class.java:123)"})</li>
<li>If no user code is found in the sanitized stack, then the API reference is outputed in the later format only.</li>
<li>If the sanitized stack is empty, returns {@code "[no operator assembly information]"}</li>
</ol>


@param source the sanitized assembly stacktrace in String format.
@return a {@link String} representing operator and operator assembly site extracted
from the assembly stack trace.
Extract operator information out of an assembly stack trace in { @link String } form ( see { @link Traces#callSiteSupplierFactory } ) which potentially has a header line that one can skip by setting { @code skipFirst } to { @code true } . <p > Most operators will result in a line of the form { @code Flux . map ⇢ user . code . Class . method ( Class . java : 123 ) } that is : <ol > <li > The top of the stack is inspected for Reactor API references and the deepest one is kept since multiple API references generally denote an alias operator . ( eg . { @code Flux . map } ) < / li > <li > The next stacktrace element is considered user code and is appended to the result with a { @code ⇢ } separator . ( eg . { @code ⇢ user . code . Class . method ( Class . java : 123 ) } ) < / li > <li > If no user code is found in the sanitized stack then the API reference is outputed in the later format only . < / li > <li > If the sanitized stack is empty returns { @code [ no operator assembly information ] } < / li > < / ol >