Skip to content

Commit

Permalink
CHE-5714:Improving search results:
Browse files Browse the repository at this point in the history
line numbers are shown for matches
multiple matches in the same file are shown individually
when you click on a search result, the editor loads the file AND jumps straight to the matching line with all instances of the search term already highlighted

Signed-off-by: Vitalii Parfonov <vparfonov@redhat.com>
  • Loading branch information
vparfonov committed Aug 3, 2017
1 parent 5661a37 commit 90e5866
Show file tree
Hide file tree
Showing 40 changed files with 1,304 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.che.api.workspace.shared.dto.NewProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.ide.api.resources.SearchResult;
import org.eclipse.che.ide.resource.Path;

import java.util.List;
Expand Down Expand Up @@ -257,7 +258,7 @@ public interface ProjectServiceClient {
* @see ItemReference
* @since 4.4.0
*/
Promise<List<ItemReference>> search(QueryExpression expression);
Promise<List<SearchResult>> search(QueryExpression expression);

/**
* Gets list of {@link SourceEstimation} for all supposed project types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,37 @@
import org.eclipse.che.api.project.shared.dto.CopyOptions;
import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.api.project.shared.dto.MoveOptions;
import org.eclipse.che.api.project.shared.dto.SearchResultDto;
import org.eclipse.che.api.project.shared.dto.SourceEstimation;
import org.eclipse.che.api.project.shared.dto.TreeElement;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.workspace.shared.dto.NewProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.ide.MimeType;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.machine.WsAgentStateController;
import org.eclipse.che.ide.api.resources.SearchResult;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.rest.AsyncRequestFactory;
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
import org.eclipse.che.ide.rest.StringUnmarshaller;
import org.eclipse.che.ide.rest.UrlBuilder;
import org.eclipse.che.ide.ui.loaders.request.LoaderFactory;
import org.eclipse.che.ide.websocket.Message;
import org.eclipse.che.ide.websocket.MessageBuilder;
import org.eclipse.che.ide.websocket.WebSocketException;
import org.eclipse.che.ide.websocket.rest.RequestCallback;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.gwt.http.client.RequestBuilder.DELETE;
import static com.google.gwt.http.client.RequestBuilder.POST;
import static com.google.gwt.http.client.RequestBuilder.PUT;
import static com.google.gwt.safehtml.shared.UriUtils.encodeAllowEscapes;
import static org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper.createFromAsyncRequest;
import static org.eclipse.che.ide.MimeType.APPLICATION_JSON;
import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;
import static org.eclipse.che.ide.rest.HTTPHeader.CONTENTTYPE;
import static org.eclipse.che.ide.rest.HTTPHeader.CONTENT_TYPE;

/**
Expand Down Expand Up @@ -143,7 +141,7 @@ public Promise<Void> importProject(Path path, SourceStorageDto source) {

/** {@inheritDoc} */
@Override
public Promise<List<ItemReference>> search(QueryExpression expression) {
public Promise<List<SearchResult>> search(QueryExpression expression) {
final String url =
encodeAllowEscapes(getBaseUrl() + SEARCH + (isNullOrEmpty(expression.getPath()) ? Path.ROOT : path(expression.getPath())));

Expand All @@ -164,7 +162,17 @@ public Promise<List<ItemReference>> search(QueryExpression expression) {
return reqFactory.createGetRequest(url + queryParameters.toString().replaceFirst("&", "?"))
.header(ACCEPT, MimeType.APPLICATION_JSON)
.loader(loaderFactory.newLoader("Searching..."))
.send(unmarshaller.newListUnmarshaller(ItemReference.class));
.send(unmarshaller.newListUnmarshaller(SearchResultDto.class)).then(
(Function<List<SearchResultDto>, List<SearchResult>>)arg -> {
if (arg.isEmpty()) {
return Collections.emptyList();
}
List<SearchResult> results = new ArrayList<>(arg.size());
for (SearchResultDto dto : arg) {
results.add(new SearchResult(dto));
}
return results;
});
}

/** {@inheritDoc} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.util.NameUtils;

import java.util.List;

/**
* Interface for resource which may contain other resources (termed its members).
* <p/>
Expand Down Expand Up @@ -436,7 +438,7 @@ public interface Container extends Resource {
* @return the {@link Promise} with array of found results
* @since 4.4.0
*/
Promise<Resource[]> search(String fileMask, String contentMask);
Promise<List<SearchResult>> search(String fileMask, String contentMask);

/**
* Returns the plain list of file tree with given {@code depth}.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.api.resources;

import org.eclipse.che.api.project.shared.SearchOccurrence;

/**
* @author Vitalii Parfonov
*/

public class SearchOccurrenceImpl implements SearchOccurrence {

private float score;
private int endOffset;
private int startOffset;
private String phrase;
private String lineContent;
private int lineNumber;

public SearchOccurrenceImpl(SearchOccurrence searchOccurrence) {
score = searchOccurrence.getScore();
endOffset = searchOccurrence.getEndOffset();
startOffset = searchOccurrence.getStartOffset();
phrase = searchOccurrence.getPhrase();
lineContent = searchOccurrence.getLineContent();
lineNumber = searchOccurrence.getLineNumber();
}

@Override
public float getScore() {
return score;
}

@Override
public void setScore(float score) {
this.score = score;
}

@Override
public String getPhrase() {
return phrase;
}

@Override
public void setPhrase(String phrase) {
this.phrase = phrase;
}

@Override
public int getEndOffset() {
return endOffset;
}

@Override
public void setEndOffset(int endOffset) {
this.endOffset = endOffset;
}

@Override
public int getStartOffset() {
return startOffset;
}

@Override
public void setStartOffset(int startOffset) {
this.startOffset = startOffset;
}

@Override
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}

@Override
public int getLineNumber() {
return lineNumber;
}

@Override
public void setLineContent(String lineContent) {
this.lineContent = lineContent;
}

@Override
public String getLineContent() {
return lineContent;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.api.resources;

import org.eclipse.che.api.project.shared.Constants;
import org.eclipse.che.api.project.shared.SearchOccurrence;
import org.eclipse.che.api.project.shared.dto.SearchOccurrenceDto;
import org.eclipse.che.api.project.shared.dto.SearchResultDto;

import java.util.ArrayList;
import java.util.List;

/**
* @author Vitalii Parfonov
*/

public class SearchResult {

private String name;
private String path;
private String project;
private String contentUrl;
private List<SearchOccurrence> occurrences;

public SearchResult(SearchResultDto searchResultDto) {
name = searchResultDto.getItemReference().getName();
path = searchResultDto.getItemReference().getPath();
project = searchResultDto.getItemReference().getProject();
if (searchResultDto.getItemReference().getLink(Constants.LINK_REL_GET_CONTENT) != null) {
contentUrl = searchResultDto.getItemReference().getLink(Constants.LINK_REL_GET_CONTENT).getHref();
}
final List<SearchOccurrenceDto> dtos = searchResultDto.getSearchOccurrences();
occurrences = new ArrayList<>(dtos.size());
for (SearchOccurrence dto : dtos) {
occurrences.add(new SearchOccurrenceImpl(dto));
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public String getProject() {
return project;
}

public void setProject(String project) {
this.project = project;
}

public List<SearchOccurrence> getOccurrences() {
return occurrences;
}

public void setOccurrences(List<SearchOccurrence> occurrences) {
this.occurrences = occurrences;
}

public String getContentUrl() {
return contentUrl;
}

public void setContentUrl(String contentUrl) {
this.contentUrl = contentUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ public interface Resources extends Tree.Resources,
@Source("part/che-logo.svg")
SVGResource cheLogo();

@Source("searchMatch.svg")
SVGResource searchMatch();

/** Interface for css resources. */
interface CoreCss extends CssResource {
String editorPaneMenuDelimiter();
Expand Down Expand Up @@ -213,7 +216,10 @@ interface CoreCss extends CssResource {

String tagsPanel();

@ClassName("codeassistant-highlight")
String codeassistantHighlight();
@ClassName("found-highlight")
String foundPhraseHighlight();

@ClassName("search-match")
String searchMatch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private void appendPlain(SafeHtmlBuilder builder, String text) {
}

private void appendHighlighted(SafeHtmlBuilder builder, String text) {
builder.appendHtmlConstant("<span class=\"" + resources.coreCss().codeassistantHighlight() + "\">");
builder.appendHtmlConstant("<span class=\"" + resources.coreCss().foundPhraseHighlight() + "\">");
builder.appendEscaped(text);
builder.appendHtmlConstant("</span>");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import com.google.inject.ImplementedBy;

import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.api.project.shared.dto.SearchResultDto;
import org.eclipse.che.ide.api.mvp.View;
import org.eclipse.che.ide.resource.Path;

Expand Down Expand Up @@ -67,6 +67,6 @@ interface ActionDelegate {
* @param items
* items of suggestions
*/
void showItems(List<ItemReference> items);
void showItems(List<SearchResultDto> items);

}
Loading

0 comments on commit 90e5866

Please sign in to comment.