Skip to content

Commit

Permalink
Merge pull request #334 from conwnet/master
Browse files Browse the repository at this point in the history
release 0.5.0
  • Loading branch information
conwnet authored Jul 5, 2021
2 parents f5e74c1 + 028cbd1 commit f8b45d6
Show file tree
Hide file tree
Showing 33 changed files with 2,252 additions and 267 deletions.
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ lib
dist
out
node_modules
**/src/vs/**
vscode-web-github1s/src/vs
vscode-web-github1s/extensions
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ The continued development and maintenance of GitHub1s is made possible by these
- [github-code-viewer](https://microsoftedge.microsoft.com/addons/detail/githubcodeviewer/jaaaapanahkknbgdbglnlchbjfhhjlpi) ([febaoshan/edge-extensions-github-code-viewer](https://github.com/febaoshan/edge-extensions-github-code-viewer))
- [Github Web IDE](https://microsoftedge.microsoft.com/addons/detail/akjbkjciknacicbnkfjbnlaeednpadcf) ([zvizvi/Github-Web-IDE](https://github.com/zvizvi/Github-Web-IDE))

### Safari Extension

- [GitHub1s-For-Safari-Extension](https://apps.apple.com/us/app/readcodeonline/id1569026520?mt=12) ([code4you2021/GitHub1s-For-Safari-Extension](https://github.com/code4you2021/GitHub1s-For-Safari-Extension))

### Tampermonkey scripts

- [Mr-B0b/TamperMonkeyScripts/vscode.js](https://github.com/Mr-B0b/TamperMonkeyScripts/blob/main/vscode.js)
Expand Down
42 changes: 31 additions & 11 deletions extensions/github1s/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { registerEventListeners } from '@/listeners';
import { PageType } from './router/types';

export async function activate(context: vscode.ExtensionContext) {
const browserUrl = (await await vscode.commands.executeCommand(
const browserUrl = (await vscode.commands.executeCommand(
'github1s.vscode.get-browser-url'
)) as string;

Expand All @@ -40,17 +40,37 @@ export async function activate(context: vscode.ExtensionContext) {

// sponsors in Status Bar
showSponsors();
await showGitpod();
showGitpod();

// open corresponding editor if there is a filePath specified in browser url
const { filePath, pageType } = await router.getState();
if (filePath && [PageType.TREE, PageType.BLOB].includes(pageType)) {
// initialize the VSCode's state
initialVSCodeState();
}

// initialize the VSCode's state according to the router url
const initialVSCodeState = async () => {
const routerState = await router.getState();
const { filePath, pageType } = routerState;
const scheme = GitHub1sFileSystemProvider.scheme;

if (filePath && pageType === PageType.TREE) {
vscode.commands.executeCommand(
pageType === PageType.TREE ? 'revealInExplorer' : 'vscode.open',
vscode.Uri.parse('').with({
scheme: GitHub1sFileSystemProvider.scheme,
path: filePath,
})
'revealInExplorer',
vscode.Uri.parse('').with({ scheme, path: filePath })
);
} else if (filePath && pageType === PageType.BLOB) {
const { startLineNumber, endLineNumber } = routerState;
const start = new vscode.Position(startLineNumber - 1, 0);
const end = new vscode.Position(endLineNumber - 1, 999999);
const documentShowOptions: vscode.TextDocumentShowOptions = startLineNumber
? { selection: new vscode.Range(start, end) }
: {};

// TODO: the selection of the opening file may be cleared
// when editor try to restore previous state in the same file
vscode.commands.executeCommand(
'vscode.open',
vscode.Uri.parse('').with({ scheme, path: filePath }),
documentShowOptions
);
} else if (pageType === PageType.PULL_LIST) {
vscode.commands.executeCommand('github1s.views.pull-request-list.focus');
Expand All @@ -59,4 +79,4 @@ export async function activate(context: vscode.ExtensionContext) {
} else if ([PageType.PULL, PageType.COMMIT].includes(pageType)) {
vscode.commands.executeCommand('workbench.scm.focus');
}
}
};
28 changes: 28 additions & 0 deletions extensions/github1s/src/helpers/func.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,31 @@ export const throttle = <T extends (...args: any[]) => any>(
timer = setTimeout(() => (timer = null), interval);
};
};

export const debounce = <T extends (...args: any[]) => any>(
func: T,
wait: number
) => {
let timer = null;
return function (...args: Parameters<T>): void {
timer && clearTimeout(timer);
timer = setTimeout(() => func.call(this, ...args), timer);
};
};

// debounce an async func. once an async func canceled, it throws a exception
export const debounceAsyncFunc = <T extends (...args: any[]) => Promise<any>>(
func: T,
wait: number
) => {
let timer = null;
let previousReject = null;
return function (...args: Parameters<T>): ReturnType<T> {
return new Promise((resolve, reject) => {
timer && clearTimeout(timer);
previousReject && previousReject();
timer = setTimeout(() => resolve(func.call(this, ...args)), wait);
previousReject = reject;
}) as ReturnType<T>;
};
};
16 changes: 16 additions & 0 deletions extensions/github1s/src/helpers/urls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @file extension url helpers
* @author netcon
*/

export const getSourcegraphUrl = (
owner: string,
repo: string,
ref: string,
path: string,
line: number,
character: number
): string => {
const repoUrl = `https://sourcegraph.com/github.com/${owner}/${repo}@${ref}`;
return `${repoUrl}/-/blob${path}#L${line + 1}:${character + 1}`;
};
65 changes: 65 additions & 0 deletions extensions/github1s/src/interfaces/sourcegraph/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @file Sourcegraph api common utils
* @author netcon
*/

import {
ApolloClient,
createHttpLink,
InMemoryCache,
} from '@apollo/client/core';
import { trimEnd, trimStart } from '@/helpers/util';

const sourcegraphLink = createHttpLink({
// Since the Sourcegraph refused the CORS check now,
// use Vercel Serverless Function to proxy it temporarily
// See `/api/sourcegraph.js`
uri: '/api/sourcegraph',
});

export const sourcegraphClient = new ApolloClient({
link: sourcegraphLink,
cache: new InMemoryCache(),
});

export const canBeConvertToRegExp = (str: string) => {
try {
new RegExp(str);
return true;
} catch (e) {
return false;
}
};

export const combineGlobsToRegExp = (globs: string[]) => {
// only support very simple globs convert now
const result = Array.from(
new Set(
globs.map((glob: string) =>
trimEnd(trimStart(glob, '*/'), '*/').replace(/^\./, '\\.')
)
)
)
// if the glob still not can be convert to a regexp, just ignore it
.filter((item) => canBeConvertToRegExp(item))
.join('|');
// ensure the result can be convert to a regexp
return canBeConvertToRegExp(result) ? result : '';
};

export const escapeRegexp = (text: string): string =>
text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');

export const getRepoRefQueryString = (
owner: string,
repo: string,
ref: string
) => {
// the string may looks like `^github\.com/conwnet/github1s$`
const repoPattern = `^${escapeRegexp(`github\.com/${owner}/${repo}`)}$`;
const repoRefQueryString =
ref.toUpperCase() === 'HEAD'
? `repo:${repoPattern}`
: `repo:${repoPattern}@${ref}`;
return repoRefQueryString;
};
137 changes: 137 additions & 0 deletions extensions/github1s/src/interfaces/sourcegraph/definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* @file Sourcegraph definition api
* @author netcon
*/

import { gql } from '@apollo/client/core';
import { sourcegraphClient } from './common';
import { getSymbolPositions } from './position';

export interface SymbolDefinition {
precise: boolean;
owner: string;
repo: string;
ref: string;
path: string;
range: {
start: {
line: number;
character: number;
};
end: {
line: number;
character: number;
};
};
}

const LSIFDefinitionsQuery = gql`
query(
$repository: String!
$ref: String!
$path: String!
$line: Int!
$character: Int!
) {
repository(name: $repository) {
commit(rev: $ref) {
blob(path: $path) {
lsif {
definitions(line: $line, character: $character) {
nodes {
resource {
path
repository {
name
}
commit {
oid
}
}
range {
start {
line
character
}
end {
line
character
}
}
}
}
}
}
}
}
}
`;

// find definitions with Sourcegraph LSIF
// https://docs.sourcegraph.com/code_intelligence/explanations/precise_code_intelligence
const getLSIFDefinitions = async (
owner: string,
repo: string,
ref: string,
path: string,
line: number,
character: number
): Promise<SymbolDefinition[]> => {
const response = await sourcegraphClient.query({
query: LSIFDefinitionsQuery,
variables: {
repository: `github.com/${owner}/${repo}`,
ref,
path: path.slice(1),
line,
character,
},
});
const definitionNodes =
response?.data?.repository?.commit?.blob?.lsif?.definitions?.nodes;
return (definitionNodes || []).map(({ resource, range }) => {
const [owner, repo] = resource.repository.name
.split('/')
.filter(Boolean)
.slice(-2);
return {
precise: true,
owner,
repo,
ref: resource.commit.oid,
path: `/${resource.path}`,
range,
};
});
};

export const getSymbolDefinitions = (
owner: string,
repo: string,
ref: string,
path: string,
line: number,
character: number,
symbol: string
): Promise<SymbolDefinition[]> => {
// if failed to find definitions from LSIF,
// fallback to search-based definitions, using
// two promise instead of `await` to request in
// parallel for getting result as soon as possible
const LSIFDefinitionsPromise = getLSIFDefinitions(
owner,
repo,
ref,
path,
line,
character
);
const searchDefinitionsPromise = getSymbolPositions(owner, repo, ref, symbol);

return LSIFDefinitionsPromise.then((LSIFDefinitions) => {
if (LSIFDefinitions.length) {
return LSIFDefinitions;
}
return searchDefinitionsPromise as Promise<SymbolDefinition[]>;
});
};
Loading

1 comment on commit f8b45d6

@vercel
Copy link

@vercel vercel bot commented on f8b45d6 Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.